[lld] r234931 - ELF: Split SectionChunks.h to SectionChunks.{h, cpp}.

Shankar Easwaran shankare at codeaurora.org
Tue Apr 14 12:37:27 PDT 2015


Thanks for doing this cleanup.

On 4/14/2015 2:31 PM, Rui Ueyama wrote:
> Author: ruiu
> Date: Tue Apr 14 14:31:42 2015
> New Revision: 234931
>
> URL: http://llvm.org/viewvc/llvm-project?rev=234931&view=rev
> Log:
> ELF: Split SectionChunks.h to SectionChunks.{h,cpp}.
>
> The size of AArch64TargetHander.cpp.o is now 4.1MB.
>
> Added:
>      lld/trunk/lib/ReaderWriter/ELF/SectionChunks.cpp
> Modified:
>      lld/trunk/lib/ReaderWriter/ELF/CMakeLists.txt
>      lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h
>
> Modified: lld/trunk/lib/ReaderWriter/ELF/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/CMakeLists.txt?rev=234931&r1=234930&r2=234931&view=diff
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/ELF/CMakeLists.txt (original)
> +++ lld/trunk/lib/ReaderWriter/ELF/CMakeLists.txt Tue Apr 14 14:31:42 2015
> @@ -5,6 +5,7 @@ add_llvm_library(lldELF
>     FileCommon.cpp
>     OutputELFWriter.cpp
>     Reader.cpp
> +  SectionChunks.cpp
>     TargetLayout.cpp
>     Writer.cpp
>     LINK_LIBS
>
> Added: lld/trunk/lib/ReaderWriter/ELF/SectionChunks.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/SectionChunks.cpp?rev=234931&view=auto
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/ELF/SectionChunks.cpp (added)
> +++ lld/trunk/lib/ReaderWriter/ELF/SectionChunks.cpp Tue Apr 14 14:31:42 2015
> @@ -0,0 +1,1008 @@
> +//===- lib/ReaderWriter/ELF/SectionChunks.h -------------------------------===//
> +//
> +//                             The LLVM Linker
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "SectionChunks.h"
> +#include "TargetLayout.h"
> +#include "lld/Core/Parallel.h"
> +#include "llvm/ADT/ArrayRef.h"
> +#include "llvm/Support/Dwarf.h"
> +
> +namespace lld {
> +namespace elf {
> +
> +template <class ELFT>
> +Section<ELFT>::Section(const ELFLinkingContext &ctx, StringRef sectionName,
> +                       StringRef chunkName, typename Chunk<ELFT>::Kind k)
> +    : Chunk<ELFT>(chunkName, k, ctx), _inputSectionName(sectionName),
> +      _outputSectionName(sectionName) {}
> +
> +template <class ELFT> int Section<ELFT>::getContentType() const {
> +  if (_flags & llvm::ELF::SHF_EXECINSTR)
> +    return Chunk<ELFT>::ContentType::Code;
> +  else if (_flags & llvm::ELF::SHF_WRITE)
> +    return Chunk<ELFT>::ContentType::Data;
> +  else if (_flags & llvm::ELF::SHF_ALLOC)
> +    return Chunk<ELFT>::ContentType::Code;
> +  else
> +    return Chunk<ELFT>::ContentType::Unknown;
> +}
> +
> +template <class ELFT>
> +AtomSection<ELFT>::AtomSection(const ELFLinkingContext &ctx,
> +                               StringRef sectionName, int32_t contentType,
> +                               int32_t permissions, int32_t order)
> +    : Section<ELFT>(ctx, sectionName, "AtomSection",
> +                    Chunk<ELFT>::Kind::AtomSection),
> +      _contentType(contentType), _contentPermissions(permissions) {
> +  this->setOrder(order);
> +
> +  switch (contentType) {
> +  case DefinedAtom::typeCode:
> +  case DefinedAtom::typeDataFast:
> +  case DefinedAtom::typeData:
> +  case DefinedAtom::typeConstant:
> +  case DefinedAtom::typeGOT:
> +  case DefinedAtom::typeStub:
> +  case DefinedAtom::typeResolver:
> +  case DefinedAtom::typeThreadData:
> +    this->_type = SHT_PROGBITS;
> +    break;
> +
> +  case DefinedAtom::typeThreadZeroFill:
> +  case DefinedAtom::typeZeroFillFast:
> +  case DefinedAtom::typeZeroFill:
> +    this->_type = SHT_NOBITS;
> +    break;
> +
> +  case DefinedAtom::typeRONote:
> +  case DefinedAtom::typeRWNote:
> +    this->_type = SHT_NOTE;
> +    break;
> +
> +  case DefinedAtom::typeNoAlloc:
> +    this->_type = SHT_PROGBITS;
> +    this->_isLoadedInMemory = false;
> +    break;
> +  }
> +
> +  switch (permissions) {
> +  case DefinedAtom::permR__:
> +    this->_flags = SHF_ALLOC;
> +    break;
> +  case DefinedAtom::permR_X:
> +    this->_flags = SHF_ALLOC | SHF_EXECINSTR;
> +    break;
> +  case DefinedAtom::permRW_:
> +  case DefinedAtom::permRW_L:
> +    this->_flags = SHF_ALLOC | SHF_WRITE;
> +    if (_contentType == DefinedAtom::typeThreadData ||
> +        _contentType == DefinedAtom::typeThreadZeroFill)
> +      this->_flags |= SHF_TLS;
> +    break;
> +  case DefinedAtom::permRWX:
> +    this->_flags = SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR;
> +    break;
> +  case DefinedAtom::perm___:
> +    this->_flags = 0;
> +    break;
> +  }
> +}
> +
> +template <class ELFT>
> +void AtomSection<ELFT>::assignVirtualAddress(uint64_t addr) {
> +  parallel_for_each(_atoms.begin(), _atoms.end(), [&](AtomLayout *ai) {
> +    ai->_virtualAddr = addr + ai->_fileOffset;
> +  });
> +}
> +
> +template <class ELFT>
> +void AtomSection<ELFT>::assignFileOffsets(uint64_t offset) {
> +  parallel_for_each(_atoms.begin(), _atoms.end(), [&](AtomLayout *ai) {
> +    ai->_fileOffset = offset + ai->_fileOffset;
> +  });
> +}
> +
> +template <class ELFT>
> +const AtomLayout *
> +AtomSection<ELFT>::findAtomLayoutByName(StringRef name) const {
> +  for (auto ai : _atoms)
> +    if (ai->_atom->name() == name)
> +      return ai;
> +  return nullptr;
> +}
> +
> +template <class ELFT>
> +void AtomSection<ELFT>::printError(const std::string &errorStr,
> +                                   const AtomLayout &atom,
> +                                   const Reference &ref) const {
> +  StringRef kindValStr;
> +  if (!this->_ctx.registry().referenceKindToString(
> +          ref.kindNamespace(), ref.kindArch(), ref.kindValue(), kindValStr)) {
> +    kindValStr = "unknown";
> +  }
> +
> +  std::string errStr =
> +      (Twine(errorStr) + " in file " + atom._atom->file().path() +
> +       ": reference from " + atom._atom->name() + "+" +
> +       Twine(ref.offsetInAtom()) + " to " + ref.target()->name() + "+" +
> +       Twine(ref.addend()) + " of type " + Twine(ref.kindValue()) + " (" +
> +       kindValStr + ")\n")
> +          .str();
> +
> +  // Take the lock to prevent output getting interleaved between threads
> +  std::lock_guard<std::mutex> lock(_outputMutex);
> +  llvm::errs() << errStr;
> +}
> +
> +/// Align the offset to the required modulus defined by the atom alignment
> +template <class ELFT>
> +uint64_t AtomSection<ELFT>::alignOffset(uint64_t offset,
> +                                        DefinedAtom::Alignment &atomAlign) {
> +  uint64_t requiredModulus = atomAlign.modulus;
> +  uint64_t alignment = atomAlign.value;
> +  uint64_t currentModulus = (offset % alignment);
> +  uint64_t retOffset = offset;
> +  if (currentModulus != requiredModulus) {
> +    if (requiredModulus > currentModulus)
> +      retOffset += requiredModulus - currentModulus;
> +    else
> +      retOffset += alignment + requiredModulus - currentModulus;
> +  }
> +  return retOffset;
> +}
> +
> +// \brief Append an atom to a Section. The atom gets pushed into a vector
> +// contains the atom, the atom file offset, the atom virtual address
> +// the atom file offset is aligned appropriately as set by the Reader
> +template <class ELFT>
> +const lld::AtomLayout *AtomSection<ELFT>::appendAtom(const Atom *atom) {
> +  const DefinedAtom *definedAtom = cast<DefinedAtom>(atom);
> +
> +  DefinedAtom::Alignment atomAlign = definedAtom->alignment();
> +  uint64_t alignment = atomAlign.value;
> +  // Align the atom to the required modulus/ align the file offset and the
> +  // memory offset separately this is required so that BSS symbols are handled
> +  // properly as the BSS symbols only occupy memory size and not file size
> +  uint64_t fOffset = alignOffset(this->fileSize(), atomAlign);
> +  uint64_t mOffset = alignOffset(this->memSize(), atomAlign);
> +  switch (definedAtom->contentType()) {
> +  case DefinedAtom::typeCode:
> +  case DefinedAtom::typeConstant:
> +  case DefinedAtom::typeData:
> +  case DefinedAtom::typeDataFast:
> +  case DefinedAtom::typeZeroFillFast:
> +  case DefinedAtom::typeGOT:
> +  case DefinedAtom::typeStub:
> +  case DefinedAtom::typeResolver:
> +  case DefinedAtom::typeThreadData:
> +  case DefinedAtom::typeRONote:
> +  case DefinedAtom::typeRWNote:
> +    _atoms.push_back(new (_alloc) lld::AtomLayout(atom, fOffset, 0));
> +    this->_fsize = fOffset + definedAtom->size();
> +    this->_msize = mOffset + definedAtom->size();
> +    DEBUG_WITH_TYPE("Section", llvm::dbgs()
> +                                   << "[" << this->name() << " " << this << "] "
> +                                   << "Adding atom: " << atom->name() << "@"
> +                                   << fOffset << "\n");
> +    break;
> +  case DefinedAtom::typeNoAlloc:
> +    _atoms.push_back(new (_alloc) lld::AtomLayout(atom, fOffset, 0));
> +    this->_fsize = fOffset + definedAtom->size();
> +    DEBUG_WITH_TYPE("Section", llvm::dbgs()
> +                                   << "[" << this->name() << " " << this << "] "
> +                                   << "Adding atom: " << atom->name() << "@"
> +                                   << fOffset << "\n");
> +    break;
> +  case DefinedAtom::typeThreadZeroFill:
> +  case DefinedAtom::typeZeroFill:
> +    _atoms.push_back(new (_alloc) lld::AtomLayout(atom, mOffset, 0));
> +    this->_msize = mOffset + definedAtom->size();
> +    break;
> +  default:
> +    llvm::dbgs() << definedAtom->contentType() << "\n";
> +    llvm_unreachable("Uexpected content type.");
> +  }
> +  // Set the section alignment to the largest alignment
> +  // std::max doesn't support uint64_t
> +  if (this->_alignment < alignment)
> +    this->_alignment = alignment;
> +
> +  if (_atoms.size())
> +    return _atoms.back();
> +  return nullptr;
> +}
> +
> +/// \brief convert the segment type to a String for diagnostics
> +///        and printing purposes
> +template <class ELFT> StringRef Section<ELFT>::segmentKindToStr() const {
> +  switch (_segmentType) {
> +  case llvm::ELF::PT_DYNAMIC:
> +    return "DYNAMIC";
> +  case llvm::ELF::PT_INTERP:
> +    return "INTERP";
> +  case llvm::ELF::PT_LOAD:
> +    return "LOAD";
> +  case llvm::ELF::PT_GNU_EH_FRAME:
> +    return "EH_FRAME";
> +  case llvm::ELF::PT_GNU_RELRO:
> +    return "GNU_RELRO";
> +  case llvm::ELF::PT_NOTE:
> +    return "NOTE";
> +  case llvm::ELF::PT_NULL:
> +    return "NULL";
> +  case llvm::ELF::PT_TLS:
> +    return "TLS";
> +  default:
> +    return "UNKNOWN";
> +  }
> +}
> +
> +/// \brief Write the section and the atom contents to the buffer
> +template <class ELFT>
> +void AtomSection<ELFT>::write(ELFWriter *writer, TargetLayout<ELFT> &layout,
> +                              llvm::FileOutputBuffer &buffer) {
> +  uint8_t *chunkBuffer = buffer.getBufferStart();
> +  bool success = true;
> +  parallel_for_each(_atoms.begin(), _atoms.end(), [&](lld::AtomLayout *ai) {
> +    DEBUG_WITH_TYPE("Section", llvm::dbgs()
> +                                   << "Writing atom: " << ai->_atom->name()
> +                                   << " | " << ai->_fileOffset << "\n");
> +    const DefinedAtom *definedAtom = cast<DefinedAtom>(ai->_atom);
> +    if (!definedAtom->occupiesDiskSpace())
> +      return;
> +    // Copy raw content of atom to file buffer.
> +    ArrayRef<uint8_t> content = definedAtom->rawContent();
> +    uint64_t contentSize = content.size();
> +    if (contentSize == 0)
> +      return;
> +    uint8_t *atomContent = chunkBuffer + ai->_fileOffset;
> +    std::memcpy(atomContent, content.data(), contentSize);
> +    const TargetRelocationHandler &relHandler =
> +        this->_ctx.getTargetHandler().getRelocationHandler();
> +    for (const auto ref : *definedAtom) {
> +      if (std::error_code ec =
> +              relHandler.applyRelocation(*writer, buffer, *ai, *ref)) {
> +        printError(ec.message(), *ai, *ref);
> +        success = false;
> +      }
> +    }
> +  });
> +  if (!success)
> +    llvm::report_fatal_error("relocating output");
> +}
> +
> +template <class ELFT> void OutputSection<ELFT>::appendSection(Chunk<ELFT> *c) {
> +  if (c->alignment() > _alignment)
> +    _alignment = c->alignment();
> +  if (const auto section = dyn_cast<Section<ELFT>>(c)) {
> +    assert(!_link && "Section already has a link!");
> +    _link = section->getLink();
> +    _shInfo = section->getInfo();
> +    _entSize = section->getEntSize();
> +    _type = section->getType();
> +    if (_flags < section->getFlags())
> +      _flags = section->getFlags();
> +    section->setOutputSection(this, (_sections.size() == 0));
> +  }
> +  _kind = c->kind();
> +  _sections.push_back(c);
> +}
> +
> +template <class ELFT>
> +StringTable<ELFT>::StringTable(const ELFLinkingContext &ctx, const char *str,
> +                               int32_t order, bool dynamic)
> +    : Section<ELFT>(ctx, str, "StringTable") {
> +  // the string table has a NULL entry for which
> +  // add an empty string
> +  _strings.push_back("");
> +  this->_fsize = 1;
> +  this->_alignment = 1;
> +  this->setOrder(order);
> +  this->_type = SHT_STRTAB;
> +  if (dynamic) {
> +    this->_flags = SHF_ALLOC;
> +    this->_msize = this->_fsize;
> +  }
> +}
> +
> +template <class ELFT> uint64_t StringTable<ELFT>::addString(StringRef symname) {
> +  if (symname.empty())
> +    return 0;
> +  StringMapTIter stringIter = _stringMap.find(symname);
> +  if (stringIter == _stringMap.end()) {
> +    _strings.push_back(symname);
> +    uint64_t offset = this->_fsize;
> +    this->_fsize += symname.size() + 1;
> +    if (this->_flags & SHF_ALLOC)
> +      this->_msize = this->_fsize;
> +    _stringMap[symname] = offset;
> +    return offset;
> +  }
> +  return stringIter->second;
> +}
> +
> +template <class ELFT>
> +void StringTable<ELFT>::write(ELFWriter *writer, TargetLayout<ELFT> &,
> +                              llvm::FileOutputBuffer &buffer) {
> +  uint8_t *chunkBuffer = buffer.getBufferStart();
> +  uint8_t *dest = chunkBuffer + this->fileOffset();
> +  for (auto si : _strings) {
> +    memcpy(dest, si.data(), si.size());
> +    dest += si.size();
> +    memcpy(dest, "", 1);
> +    dest += 1;
> +  }
> +}
> +
> +/// ELF Symbol Table
> +template <class ELFT>
> +SymbolTable<ELFT>::SymbolTable(const ELFLinkingContext &ctx, const char *str,
> +                               int32_t order)
> +    : Section<ELFT>(ctx, str, "SymbolTable") {
> +  this->setOrder(order);
> +  Elf_Sym symbol;
> +  std::memset(&symbol, 0, sizeof(Elf_Sym));
> +  _symbolTable.push_back(SymbolEntry(nullptr, symbol, nullptr));
> +  this->_entSize = sizeof(Elf_Sym);
> +  this->_fsize = sizeof(Elf_Sym);
> +  this->_alignment = sizeof(Elf_Addr);
> +  this->_type = SHT_SYMTAB;
> +}
> +
> +template <class ELFT>
> +void SymbolTable<ELFT>::addDefinedAtom(Elf_Sym &sym, const DefinedAtom *da,
> +                                       int64_t addr) {
> +  unsigned char binding = 0, type = 0;
> +  sym.st_size = da->size();
> +  DefinedAtom::ContentType ct;
> +  switch (ct = da->contentType()) {
> +  case DefinedAtom::typeCode:
> +  case DefinedAtom::typeStub:
> +    sym.st_value = addr;
> +    type = llvm::ELF::STT_FUNC;
> +    break;
> +  case DefinedAtom::typeResolver:
> +    sym.st_value = addr;
> +    type = llvm::ELF::STT_GNU_IFUNC;
> +    break;
> +  case DefinedAtom::typeDataFast:
> +  case DefinedAtom::typeData:
> +  case DefinedAtom::typeConstant:
> +    sym.st_value = addr;
> +    type = llvm::ELF::STT_OBJECT;
> +    break;
> +  case DefinedAtom::typeGOT:
> +    sym.st_value = addr;
> +    type = llvm::ELF::STT_NOTYPE;
> +    break;
> +  case DefinedAtom::typeZeroFill:
> +  case DefinedAtom::typeZeroFillFast:
> +    type = llvm::ELF::STT_OBJECT;
> +    sym.st_value = addr;
> +    break;
> +  case DefinedAtom::typeThreadData:
> +  case DefinedAtom::typeThreadZeroFill:
> +    type = llvm::ELF::STT_TLS;
> +    sym.st_value = addr;
> +    break;
> +  default:
> +    type = llvm::ELF::STT_NOTYPE;
> +  }
> +  if (da->customSectionName() == da->name())
> +    type = llvm::ELF::STT_SECTION;
> +
> +  if (da->scope() == DefinedAtom::scopeTranslationUnit)
> +    binding = llvm::ELF::STB_LOCAL;
> +  else
> +    binding = llvm::ELF::STB_GLOBAL;
> +
> +  sym.setBindingAndType(binding, type);
> +}
> +
> +template <class ELFT>
> +void SymbolTable<ELFT>::addAbsoluteAtom(Elf_Sym &sym, const AbsoluteAtom *aa,
> +                                        int64_t addr) {
> +  unsigned char binding = 0, type = 0;
> +  type = llvm::ELF::STT_OBJECT;
> +  sym.st_shndx = llvm::ELF::SHN_ABS;
> +  switch (aa->scope()) {
> +  case AbsoluteAtom::scopeLinkageUnit:
> +    sym.setVisibility(llvm::ELF::STV_HIDDEN);
> +    binding = llvm::ELF::STB_LOCAL;
> +    break;
> +  case AbsoluteAtom::scopeTranslationUnit:
> +    binding = llvm::ELF::STB_LOCAL;
> +    break;
> +  case AbsoluteAtom::scopeGlobal:
> +    binding = llvm::ELF::STB_GLOBAL;
> +    break;
> +  }
> +  sym.st_value = addr;
> +  sym.setBindingAndType(binding, type);
> +}
> +
> +template <class ELFT>
> +void SymbolTable<ELFT>::addSharedLibAtom(Elf_Sym &sym,
> +                                         const SharedLibraryAtom *aa) {
> +  unsigned char binding = 0, type = 0;
> +  if (aa->type() == SharedLibraryAtom::Type::Data) {
> +    type = llvm::ELF::STT_OBJECT;
> +    sym.st_size = aa->size();
> +  } else
> +    type = llvm::ELF::STT_FUNC;
> +  sym.st_shndx = llvm::ELF::SHN_UNDEF;
> +  binding = llvm::ELF::STB_GLOBAL;
> +  sym.setBindingAndType(binding, type);
> +}
> +
> +template <class ELFT>
> +void SymbolTable<ELFT>::addUndefinedAtom(Elf_Sym &sym,
> +                                         const UndefinedAtom *ua) {
> +  unsigned char binding = 0, type = 0;
> +  sym.st_value = 0;
> +  type = llvm::ELF::STT_NOTYPE;
> +  if (ua->canBeNull())
> +    binding = llvm::ELF::STB_WEAK;
> +  else
> +    binding = llvm::ELF::STB_GLOBAL;
> +  sym.setBindingAndType(binding, type);
> +}
> +
> +/// Add a symbol to the symbol Table, definedAtoms which get added to the symbol
> +/// section don't have their virtual addresses set at the time of adding the
> +/// symbol to the symbol table(Example: dynamic symbols), the addresses needs
> +/// to be updated in the table before writing the dynamic symbol table
> +/// information
> +template <class ELFT>
> +void SymbolTable<ELFT>::addSymbol(const Atom *atom, int32_t sectionIndex,
> +                                  uint64_t addr,
> +                                  const lld::AtomLayout *atomLayout) {
> +  Elf_Sym symbol;
> +
> +  if (atom->name().empty())
> +    return;
> +
> +  symbol.st_name = _stringSection->addString(atom->name());
> +  symbol.st_size = 0;
> +  symbol.st_shndx = sectionIndex;
> +  symbol.st_value = 0;
> +  symbol.st_other = 0;
> +  symbol.setVisibility(llvm::ELF::STV_DEFAULT);
> +
> +  // Add all the atoms
> +  if (const DefinedAtom *da = dyn_cast<const DefinedAtom>(atom))
> +    addDefinedAtom(symbol, da, addr);
> +  else if (const AbsoluteAtom *aa = dyn_cast<const AbsoluteAtom>(atom))
> +    addAbsoluteAtom(symbol, aa, addr);
> +  else if (isa<const SharedLibraryAtom>(atom))
> +    addSharedLibAtom(symbol, dyn_cast<SharedLibraryAtom>(atom));
> +  else
> +    addUndefinedAtom(symbol, dyn_cast<UndefinedAtom>(atom));
> +
> +  _symbolTable.push_back(SymbolEntry(atom, symbol, atomLayout));
> +  this->_fsize += sizeof(Elf_Sym);
> +  if (this->_flags & SHF_ALLOC)
> +    this->_msize = this->_fsize;
> +}
> +
> +template <class ELFT> void SymbolTable<ELFT>::finalize(bool sort) {
> +  // sh_info should be one greater than last symbol with STB_LOCAL binding
> +  // we sort the symbol table to keep all local symbols at the beginning
> +  if (sort)
> +    sortSymbols();
> +
> +  uint16_t shInfo = 0;
> +  for (const auto &i : _symbolTable) {
> +    if (i._symbol.getBinding() != llvm::ELF::STB_LOCAL)
> +      break;
> +    shInfo++;
> +  }
> +  this->_info = shInfo;
> +  this->_link = _stringSection->ordinal();
> +  if (this->_outputSection) {
> +    this->_outputSection->setInfo(this->_info);
> +    this->_outputSection->setLink(this->_link);
> +  }
> +}
> +
> +template <class ELFT>
> +void SymbolTable<ELFT>::write(ELFWriter *writer, TargetLayout<ELFT> &,
> +                              llvm::FileOutputBuffer &buffer) {
> +  uint8_t *chunkBuffer = buffer.getBufferStart();
> +  uint8_t *dest = chunkBuffer + this->fileOffset();
> +  for (const auto &sti : _symbolTable) {
> +    memcpy(dest, &sti._symbol, sizeof(Elf_Sym));
> +    dest += sizeof(Elf_Sym);
> +  }
> +}
> +
> +template <class ELFT>
> +DynamicSymbolTable<ELFT>::DynamicSymbolTable(const ELFLinkingContext &ctx,
> +                                             TargetLayout<ELFT> &layout,
> +                                             const char *str, int32_t order)
> +    : SymbolTable<ELFT>(ctx, str, order), _layout(layout) {
> +  this->_type = SHT_DYNSYM;
> +  this->_flags = SHF_ALLOC;
> +  this->_msize = this->_fsize;
> +}
> +
> +template <class ELFT> void DynamicSymbolTable<ELFT>::addSymbolsToHashTable() {
> +  int index = 0;
> +  for (auto &ste : this->_symbolTable) {
> +    if (!ste._atom)
> +      _hashTable->addSymbol("", index);
> +    else
> +      _hashTable->addSymbol(ste._atom->name(), index);
> +    ++index;
> +  }
> +}
> +
> +template <class ELFT> void DynamicSymbolTable<ELFT>::finalize() {
> +  // Defined symbols which have been added into the dynamic symbol table
> +  // don't have their addresses known until addresses have been assigned
> +  // so let's update the symbol values after they have got assigned
> +  for (auto &ste : this->_symbolTable) {
> +    const lld::AtomLayout *atomLayout = ste._atomLayout;
> +    if (!atomLayout)
> +      continue;
> +    ste._symbol.st_value = atomLayout->_virtualAddr;
> +  }
> +
> +  // Don't sort the symbols
> +  SymbolTable<ELFT>::finalize(false);
> +}
> +
> +template <class ELFT>
> +RelocationTable<ELFT>::RelocationTable(const ELFLinkingContext &ctx,
> +                                       StringRef str, int32_t order)
> +    : Section<ELFT>(ctx, str, "RelocationTable") {
> +  this->setOrder(order);
> +  this->_flags = SHF_ALLOC;
> +  // Set the alignment properly depending on the target architecture
> +  this->_alignment = ELFT::Is64Bits ? 8 : 4;
> +  if (ctx.isRelaOutputFormat()) {
> +    this->_entSize = sizeof(Elf_Rela);
> +    this->_type = SHT_RELA;
> +  } else {
> +    this->_entSize = sizeof(Elf_Rel);
> +    this->_type = SHT_REL;
> +  }
> +}
> +
> +template <class ELFT>
> +uint32_t RelocationTable<ELFT>::addRelocation(const DefinedAtom &da,
> +                                              const Reference &r) {
> +  _relocs.emplace_back(&da, &r);
> +  this->_fsize = _relocs.size() * this->_entSize;
> +  this->_msize = this->_fsize;
> +  return _relocs.size() - 1;
> +}
> +
> +template <class ELFT>
> +bool RelocationTable<ELFT>::getRelocationIndex(const Reference &r,
> +                                               uint32_t &res) {
> +  auto rel = std::find_if(
> +      _relocs.begin(), _relocs.end(),
> +      [&](const std::pair<const DefinedAtom *, const Reference *> &p) {
> +        if (p.second == &r)
> +          return true;
> +        return false;
> +      });
> +  if (rel == _relocs.end())
> +    return false;
> +  res = std::distance(_relocs.begin(), rel);
> +  return true;
> +}
> +
> +template <class ELFT>
> +bool RelocationTable<ELFT>::canModifyReadonlySection() const {
> +  for (const auto &rel : _relocs) {
> +    const DefinedAtom *atom = rel.first;
> +    if ((atom->permissions() & DefinedAtom::permRW_) != DefinedAtom::permRW_)
> +      return true;
> +  }
> +  return false;
> +}
> +
> +template <class ELFT> void RelocationTable<ELFT>::finalize() {
> +  this->_link = _symbolTable ? _symbolTable->ordinal() : 0;
> +  if (this->_outputSection)
> +    this->_outputSection->setLink(this->_link);
> +}
> +
> +template <class ELFT>
> +void RelocationTable<ELFT>::write(ELFWriter *writer, TargetLayout<ELFT> &layout,
> +                                  llvm::FileOutputBuffer &buffer) {
> +  uint8_t *chunkBuffer = buffer.getBufferStart();
> +  uint8_t *dest = chunkBuffer + this->fileOffset();
> +  for (const auto &rel : _relocs) {
> +    if (this->_ctx.isRelaOutputFormat()) {
> +      auto &r = *reinterpret_cast<Elf_Rela *>(dest);
> +      writeRela(writer, r, *rel.first, *rel.second);
> +      DEBUG_WITH_TYPE("ELFRelocationTable",
> +                      llvm::dbgs()
> +                          << rel.second->kindValue() << " relocation at "
> +                          << rel.first->name() << "@" << r.r_offset << " to "
> +                          << rel.second->target()->name() << "@" << r.r_addend
> +                          << "\n";);
> +    } else {
> +      auto &r = *reinterpret_cast<Elf_Rel *>(dest);
> +      writeRel(writer, r, *rel.first, *rel.second);
> +      DEBUG_WITH_TYPE("ELFRelocationTable",
> +                      llvm::dbgs() << rel.second->kindValue()
> +                                   << " relocation at " << rel.first->name()
> +                                   << "@" << r.r_offset << " to "
> +                                   << rel.second->target()->name() << "\n";);
> +    }
> +    dest += this->_entSize;
> +  }
> +}
> +
> +template <class ELFT>
> +void RelocationTable<ELFT>::writeRela(ELFWriter *writer, Elf_Rela &r,
> +                                      const DefinedAtom &atom,
> +                                      const Reference &ref) {
> +  r.setSymbolAndType(getSymbolIndex(ref.target()), ref.kindValue(), false);
> +  r.r_offset = writer->addressOfAtom(&atom) + ref.offsetInAtom();
> +  // The addend is used only by relative relocations
> +  if (this->_ctx.isRelativeReloc(ref))
> +    r.r_addend = writer->addressOfAtom(ref.target()) + ref.addend();
> +  else
> +    r.r_addend = 0;
> +}
> +
> +template <class ELFT>
> +void RelocationTable<ELFT>::writeRel(ELFWriter *writer, Elf_Rel &r,
> +                                     const DefinedAtom &atom,
> +                                     const Reference &ref) {
> +  r.setSymbolAndType(getSymbolIndex(ref.target()), ref.kindValue(), false);
> +  r.r_offset = writer->addressOfAtom(&atom) + ref.offsetInAtom();
> +}
> +
> +template <class ELFT>
> +uint32_t RelocationTable<ELFT>::getSymbolIndex(const Atom *a) {
> +  return _symbolTable ? _symbolTable->getSymbolTableIndex(a)
> +                      : (uint32_t)STN_UNDEF;
> +}
> +
> +template <class ELFT>
> +DynamicTable<ELFT>::DynamicTable(const ELFLinkingContext &ctx,
> +                                 TargetLayout<ELFT> &layout, StringRef str,
> +                                 int32_t order)
> +    : Section<ELFT>(ctx, str, "DynamicSection"), _layout(layout) {
> +  this->setOrder(order);
> +  this->_entSize = sizeof(Elf_Dyn);
> +  this->_alignment = ELFT::Is64Bits ? 8 : 4;
> +  // Reserve space for the DT_NULL entry.
> +  this->_fsize = sizeof(Elf_Dyn);
> +  this->_msize = sizeof(Elf_Dyn);
> +  this->_type = SHT_DYNAMIC;
> +  this->_flags = SHF_ALLOC;
> +}
> +
> +template <class ELFT> std::size_t DynamicTable<ELFT>::addEntry(Elf_Dyn e) {
> +  _entries.push_back(e);
> +  this->_fsize = (_entries.size() * sizeof(Elf_Dyn)) + sizeof(Elf_Dyn);
> +  this->_msize = this->_fsize;
> +  return _entries.size() - 1;
> +}
> +
> +template <class ELFT>
> +void DynamicTable<ELFT>::write(ELFWriter *writer, TargetLayout<ELFT> &layout,
> +                               llvm::FileOutputBuffer &buffer) {
> +  uint8_t *chunkBuffer = buffer.getBufferStart();
> +  uint8_t *dest = chunkBuffer + this->fileOffset();
> +  // Add the null entry.
> +  Elf_Dyn d;
> +  d.d_tag = 0;
> +  d.d_un.d_val = 0;
> +  _entries.push_back(d);
> +  std::memcpy(dest, _entries.data(), this->_fsize);
> +}
> +
> +template <class ELFT> void DynamicTable<ELFT>::createDefaultEntries() {
> +  bool isRela = this->_ctx.isRelaOutputFormat();
> +
> +  Elf_Dyn dyn;
> +  dyn.d_un.d_val = 0;
> +
> +  dyn.d_tag = DT_HASH;
> +  _dt_hash = addEntry(dyn);
> +  dyn.d_tag = DT_STRTAB;
> +  _dt_strtab = addEntry(dyn);
> +  dyn.d_tag = DT_SYMTAB;
> +  _dt_symtab = addEntry(dyn);
> +  dyn.d_tag = DT_STRSZ;
> +  _dt_strsz = addEntry(dyn);
> +  dyn.d_tag = DT_SYMENT;
> +  _dt_syment = addEntry(dyn);
> +  if (_layout.hasDynamicRelocationTable()) {
> +    dyn.d_tag = isRela ? DT_RELA : DT_REL;
> +    _dt_rela = addEntry(dyn);
> +    dyn.d_tag = isRela ? DT_RELASZ : DT_RELSZ;
> +    _dt_relasz = addEntry(dyn);
> +    dyn.d_tag = isRela ? DT_RELAENT : DT_RELENT;
> +    _dt_relaent = addEntry(dyn);
> +
> +    if (_layout.getDynamicRelocationTable()->canModifyReadonlySection()) {
> +      dyn.d_tag = DT_TEXTREL;
> +      _dt_textrel = addEntry(dyn);
> +    }
> +  }
> +  if (_layout.hasPLTRelocationTable()) {
> +    dyn.d_tag = DT_PLTRELSZ;
> +    _dt_pltrelsz = addEntry(dyn);
> +    dyn.d_tag = getGotPltTag();
> +    _dt_pltgot = addEntry(dyn);
> +    dyn.d_tag = DT_PLTREL;
> +    dyn.d_un.d_val = isRela ? DT_RELA : DT_REL;
> +    _dt_pltrel = addEntry(dyn);
> +    dyn.d_un.d_val = 0;
> +    dyn.d_tag = DT_JMPREL;
> +    _dt_jmprel = addEntry(dyn);
> +  }
> +}
> +
> +template <class ELFT> void DynamicTable<ELFT>::doPreFlight() {
> +  Elf_Dyn dyn;
> +  dyn.d_un.d_val = 0;
> +  auto initArray = _layout.findOutputSection(".init_array");
> +  auto finiArray = _layout.findOutputSection(".fini_array");
> +  if (initArray) {
> +    dyn.d_tag = DT_INIT_ARRAY;
> +    _dt_init_array = addEntry(dyn);
> +    dyn.d_tag = DT_INIT_ARRAYSZ;
> +    _dt_init_arraysz = addEntry(dyn);
> +  }
> +  if (finiArray) {
> +    dyn.d_tag = DT_FINI_ARRAY;
> +    _dt_fini_array = addEntry(dyn);
> +    dyn.d_tag = DT_FINI_ARRAYSZ;
> +    _dt_fini_arraysz = addEntry(dyn);
> +  }
> +  if (getInitAtomLayout()) {
> +    dyn.d_tag = DT_INIT;
> +    _dt_init = addEntry(dyn);
> +  }
> +  if (getFiniAtomLayout()) {
> +    dyn.d_tag = DT_FINI;
> +    _dt_fini = addEntry(dyn);
> +  }
> +}
> +
> +template <class ELFT> void DynamicTable<ELFT>::finalize() {
> +  StringTable<ELFT> *dynamicStringTable = _dynamicSymbolTable->getStringTable();
> +  this->_link = dynamicStringTable->ordinal();
> +  if (this->_outputSection) {
> +    this->_outputSection->setType(this->_type);
> +    this->_outputSection->setInfo(this->_info);
> +    this->_outputSection->setLink(this->_link);
> +  }
> +}
> +
> +template <class ELFT> void DynamicTable<ELFT>::updateDynamicTable() {
> +  StringTable<ELFT> *dynamicStringTable = _dynamicSymbolTable->getStringTable();
> +  _entries[_dt_hash].d_un.d_val = _hashTable->virtualAddr();
> +  _entries[_dt_strtab].d_un.d_val = dynamicStringTable->virtualAddr();
> +  _entries[_dt_symtab].d_un.d_val = _dynamicSymbolTable->virtualAddr();
> +  _entries[_dt_strsz].d_un.d_val = dynamicStringTable->memSize();
> +  _entries[_dt_syment].d_un.d_val = _dynamicSymbolTable->getEntSize();
> +  auto initArray = _layout.findOutputSection(".init_array");
> +  if (initArray) {
> +    _entries[_dt_init_array].d_un.d_val = initArray->virtualAddr();
> +    _entries[_dt_init_arraysz].d_un.d_val = initArray->memSize();
> +  }
> +  auto finiArray = _layout.findOutputSection(".fini_array");
> +  if (finiArray) {
> +    _entries[_dt_fini_array].d_un.d_val = finiArray->virtualAddr();
> +    _entries[_dt_fini_arraysz].d_un.d_val = finiArray->memSize();
> +  }
> +  if (const auto *al = getInitAtomLayout())
> +    _entries[_dt_init].d_un.d_val = getAtomVirtualAddress(al);
> +  if (const auto *al = getFiniAtomLayout())
> +    _entries[_dt_fini].d_un.d_val = getAtomVirtualAddress(al);
> +  if (_layout.hasDynamicRelocationTable()) {
> +    auto relaTbl = _layout.getDynamicRelocationTable();
> +    _entries[_dt_rela].d_un.d_val = relaTbl->virtualAddr();
> +    _entries[_dt_relasz].d_un.d_val = relaTbl->memSize();
> +    _entries[_dt_relaent].d_un.d_val = relaTbl->getEntSize();
> +  }
> +  if (_layout.hasPLTRelocationTable()) {
> +    auto relaTbl = _layout.getPLTRelocationTable();
> +    _entries[_dt_jmprel].d_un.d_val = relaTbl->virtualAddr();
> +    _entries[_dt_pltrelsz].d_un.d_val = relaTbl->memSize();
> +    auto gotplt = _layout.findOutputSection(".got.plt");
> +    _entries[_dt_pltgot].d_un.d_val = gotplt->virtualAddr();
> +  }
> +}
> +
> +template <class ELFT>
> +const AtomLayout *DynamicTable<ELFT>::getInitAtomLayout() {
> +  auto al = _layout.findAtomLayoutByName(this->_ctx.initFunction());
> +  if (al && isa<DefinedAtom>(al->_atom))
> +    return al;
> +  return nullptr;
> +}
> +
> +template <class ELFT>
> +const AtomLayout *DynamicTable<ELFT>::getFiniAtomLayout() {
> +  auto al = _layout.findAtomLayoutByName(this->_ctx.finiFunction());
> +  if (al && isa<DefinedAtom>(al->_atom))
> +    return al;
> +  return nullptr;
> +}
> +
> +template <class ELFT>
> +InterpSection<ELFT>::InterpSection(const ELFLinkingContext &ctx, StringRef str,
> +                                   int32_t order, StringRef interp)
> +    : Section<ELFT>(ctx, str, "Dynamic:Interp"), _interp(interp) {
> +  this->setOrder(order);
> +  this->_alignment = 1;
> +  // + 1 for null term.
> +  this->_fsize = interp.size() + 1;
> +  this->_msize = this->_fsize;
> +  this->_type = SHT_PROGBITS;
> +  this->_flags = SHF_ALLOC;
> +}
> +
> +template <class ELFT>
> +void InterpSection<ELFT>::write(ELFWriter *writer, TargetLayout<ELFT> &layout,
> +                                llvm::FileOutputBuffer &buffer) {
> +  uint8_t *chunkBuffer = buffer.getBufferStart();
> +  uint8_t *dest = chunkBuffer + this->fileOffset();
> +  std::memcpy(dest, _interp.data(), _interp.size());
> +}
> +
> +template <class ELFT>
> +HashSection<ELFT>::HashSection(const ELFLinkingContext &ctx, StringRef name,
> +                               int32_t order)
> +    : Section<ELFT>(ctx, name, "Dynamic:Hash") {
> +  this->setOrder(order);
> +  this->_entSize = 4;
> +  this->_type = SHT_HASH;
> +  this->_flags = SHF_ALLOC;
> +  this->_alignment = ELFT::Is64Bits ? 8 : 4;
> +  this->_fsize = 0;
> +  this->_msize = 0;
> +}
> +
> +template <class ELFT>
> +void HashSection<ELFT>::addSymbol(StringRef name, uint32_t index) {
> +  SymbolTableEntry ste;
> +  ste._name = name;
> +  ste._index = index;
> +  _entries.push_back(ste);
> +}
> +
> +/// \brief Set the dynamic symbol table
> +template <class ELFT>
> +void HashSection<ELFT>::setSymbolTable(
> +    const DynamicSymbolTable<ELFT> *symbolTable) {
> +  _symbolTable = symbolTable;
> +}
> +
> +template <class ELFT> void HashSection<ELFT>::doPreFlight() {
> +  // The number of buckets to use for a certain number of symbols.
> +  // If there are less than 3 symbols, 1 bucket will be used. If
> +  // there are less than 17 symbols, 3 buckets will be used, and so
> +  // forth. The bucket numbers are defined by GNU ld. We use the
> +  // same rules here so we generate hash sections with the same
> +  // size as those generated by GNU ld.
> +  uint32_t hashBuckets[] = {1,     3,     17,    37,     67,    97,   131,
> +                            197,   263,   521,   1031,   2053,  4099, 8209,
> +                            16411, 32771, 65537, 131101, 262147};
> +  int hashBucketsCount = sizeof(hashBuckets) / sizeof(uint32_t);
> +
> +  unsigned int bucketsCount = 0;
> +  unsigned int dynSymCount = _entries.size();
> +
> +  // Get the number of buckes that we want to use
> +  for (int i = 0; i < hashBucketsCount; ++i) {
> +    if (dynSymCount < hashBuckets[i])
> +      break;
> +    bucketsCount = hashBuckets[i];
> +  }
> +  _buckets.resize(bucketsCount);
> +  _chains.resize(_entries.size());
> +
> +  // Create the hash table for the dynamic linker
> +  for (auto ai : _entries) {
> +    unsigned int dynsymIndex = ai._index;
> +    unsigned int bucketpos = llvm::object::elf_hash(ai._name) % bucketsCount;
> +    _chains[dynsymIndex] = _buckets[bucketpos];
> +    _buckets[bucketpos] = dynsymIndex;
> +  }
> +
> +  this->_fsize = (2 + _chains.size() + _buckets.size()) * sizeof(uint32_t);
> +  this->_msize = this->_fsize;
> +}
> +
> +template <class ELFT> void HashSection<ELFT>::finalize() {
> +  this->_link = _symbolTable ? _symbolTable->ordinal() : 0;
> +  if (this->_outputSection)
> +    this->_outputSection->setLink(this->_link);
> +}
> +
> +template <class ELFT>
> +void HashSection<ELFT>::write(ELFWriter *writer, TargetLayout<ELFT> &layout,
> +                              llvm::FileOutputBuffer &buffer) {
> +  uint8_t *chunkBuffer = buffer.getBufferStart();
> +  uint8_t *dest = chunkBuffer + this->fileOffset();
> +  Elf_Word bucketChainCounts[2];
> +  bucketChainCounts[0] = _buckets.size();
> +  bucketChainCounts[1] = _chains.size();
> +  std::memcpy(dest, bucketChainCounts, sizeof(bucketChainCounts));
> +  dest += sizeof(bucketChainCounts);
> +  // write bucket values
> +  std::memcpy(dest, _buckets.data(), _buckets.size() * sizeof(Elf_Word));
> +  dest += _buckets.size() * sizeof(Elf_Word);
> +  // write chain values
> +  std::memcpy(dest, _chains.data(), _chains.size() * sizeof(Elf_Word));
> +}
> +
> +template <class ELFT>
> +EHFrameHeader<ELFT>::EHFrameHeader(const ELFLinkingContext &ctx, StringRef name,
> +                                   TargetLayout<ELFT> &layout, int32_t order)
> +    : Section<ELFT>(ctx, name, "EHFrameHeader"), _layout(layout) {
> +  this->setOrder(order);
> +  this->_entSize = 0;
> +  this->_type = SHT_PROGBITS;
> +  this->_flags = SHF_ALLOC;
> +  this->_alignment = ELFT::Is64Bits ? 8 : 4;
> +  // Minimum size for empty .eh_frame_hdr.
> +  this->_fsize = 1 + 1 + 1 + 1 + 4;
> +  this->_msize = this->_fsize;
> +}
> +
> +template <class ELFT> void EHFrameHeader<ELFT>::doPreFlight() {
> +  // TODO: Generate a proper binary search table.
> +}
> +
> +template <class ELFT> void EHFrameHeader<ELFT>::finalize() {
> +  OutputSection<ELFT> *s = _layout.findOutputSection(".eh_frame");
> +  OutputSection<ELFT> *h = _layout.findOutputSection(".eh_frame_hdr");
> +  if (s && h)
> +    _ehFrameOffset = s->virtualAddr() - (h->virtualAddr() + 4);
> +}
> +
> +template <class ELFT>
> +void EHFrameHeader<ELFT>::write(ELFWriter *writer, TargetLayout<ELFT> &layout,
> +                                llvm::FileOutputBuffer &buffer) {
> +  uint8_t *chunkBuffer = buffer.getBufferStart();
> +  uint8_t *dest = chunkBuffer + this->fileOffset();
> +  int pos = 0;
> +  dest[pos++] = 1; // version
> +  dest[pos++] = llvm::dwarf::DW_EH_PE_pcrel |
> +                llvm::dwarf::DW_EH_PE_sdata4; // eh_frame_ptr_enc
> +  dest[pos++] = llvm::dwarf::DW_EH_PE_omit;   // fde_count_enc
> +  dest[pos++] = llvm::dwarf::DW_EH_PE_omit;   // table_enc
> +  *reinterpret_cast<typename llvm::object::ELFFile<ELFT>::Elf_Sword *>(
> +      dest + pos) = _ehFrameOffset;
> +}
> +
> +#define INSTANTIATE(klass)        \
> +  template class klass<ELF32LE>;  \
> +  template class klass<ELF32BE>;  \
> +  template class klass<ELF64LE>;  \
> +  template class klass<ELF64BE>;
> +
> +INSTANTIATE(AtomSection);
> +INSTANTIATE(DynamicSymbolTable);
> +INSTANTIATE(DynamicTable);
> +INSTANTIATE(EHFrameHeader);
> +INSTANTIATE(HashSection);
> +INSTANTIATE(InterpSection);
> +INSTANTIATE(OutputSection);
> +INSTANTIATE(RelocationTable);
> +INSTANTIATE(Section);
> +INSTANTIATE(StringTable);
> +INSTANTIATE(SymbolTable);
> +
> +} // end namespace elf
> +} // end namespace lld
>
> Modified: lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h?rev=234931&r1=234930&r2=234931&view=diff
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h (original)
> +++ lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h Tue Apr 14 14:31:42 2015
> @@ -14,17 +14,13 @@
>   #include "TargetHandler.h"
>   #include "Writer.h"
>   #include "lld/Core/DefinedAtom.h"
> -#include "lld/Core/Parallel.h"
>   #include "lld/Core/range.h"
>   #include "lld/ReaderWriter/AtomLayout.h"
>   #include "lld/ReaderWriter/ELFLinkingContext.h"
> -#include "llvm/ADT/ArrayRef.h"
>   #include "llvm/ADT/DenseMap.h"
>   #include "llvm/ADT/StringExtras.h"
>   #include "llvm/Object/ELF.h"
>   #include "llvm/Support/Allocator.h"
> -#include "llvm/Support/Debug.h"
> -#include "llvm/Support/Dwarf.h"
>   #include "llvm/Support/ELF.h"
>   #include "llvm/Support/ErrorHandling.h"
>   #include "llvm/Support/FileOutputBuffer.h"
> @@ -43,9 +39,7 @@ template <class ELFT> class Section : pu
>   public:
>     Section(const ELFLinkingContext &ctx, StringRef sectionName,
>             StringRef chunkName,
> -          typename Chunk<ELFT>::Kind k = Chunk<ELFT>::Kind::ELFSection)
> -      : Chunk<ELFT>(chunkName, k, ctx), _inputSectionName(sectionName),
> -        _outputSectionName(sectionName) {}
> +          typename Chunk<ELFT>::Kind k = Chunk<ELFT>::Kind::ELFSection);
>   
>     /// \brief Modify the section contents before assigning virtual addresses
>     //  or assigning file offsets
> @@ -69,21 +63,13 @@ public:
>     uint32_t getType() const { return _type; }
>     uint32_t getLink() const { return _link; }
>     uint32_t getInfo() const { return _info; }
> +
>     typename TargetLayout<ELFT>::SegmentType getSegmentType() const {
>       return _segmentType;
>     }
>   
>     /// \brief Return the type of content that the section contains
> -  int getContentType() const override {
> -    if (_flags & llvm::ELF::SHF_EXECINSTR)
> -      return Chunk<ELFT>::ContentType::Code;
> -    else if (_flags & llvm::ELF::SHF_WRITE)
> -      return Chunk<ELFT>::ContentType::Data;
> -    else if (_flags & llvm::ELF::SHF_ALLOC)
> -      return Chunk<ELFT>::ContentType::Code;
> -    else
> -      return Chunk<ELFT>::ContentType::Unknown;
> -  }
> +  int getContentType() const override;
>   
>     /// \brief convert the segment type to a String for diagnostics and printing
>     /// purposes
> @@ -159,63 +145,7 @@ protected:
>   template <class ELFT> class AtomSection : public Section<ELFT> {
>   public:
>     AtomSection(const ELFLinkingContext &ctx, StringRef sectionName,
> -              int32_t contentType, int32_t permissions, int32_t order)
> -      : Section<ELFT>(ctx, sectionName, "AtomSection",
> -                      Chunk<ELFT>::Kind::AtomSection),
> -        _contentType(contentType), _contentPermissions(permissions) {
> -    this->setOrder(order);
> -
> -    switch (contentType) {
> -    case DefinedAtom::typeCode:
> -    case DefinedAtom::typeDataFast:
> -    case DefinedAtom::typeData:
> -    case DefinedAtom::typeConstant:
> -    case DefinedAtom::typeGOT:
> -    case DefinedAtom::typeStub:
> -    case DefinedAtom::typeResolver:
> -    case DefinedAtom::typeThreadData:
> -      this->_type = SHT_PROGBITS;
> -      break;
> -
> -    case DefinedAtom::typeThreadZeroFill:
> -    case DefinedAtom::typeZeroFillFast:
> -    case DefinedAtom::typeZeroFill:
> -      this->_type = SHT_NOBITS;
> -      break;
> -
> -    case DefinedAtom::typeRONote:
> -    case DefinedAtom::typeRWNote:
> -      this->_type = SHT_NOTE;
> -      break;
> -
> -    case DefinedAtom::typeNoAlloc:
> -      this->_type = SHT_PROGBITS;
> -      this->_isLoadedInMemory = false;
> -      break;
> -    }
> -
> -    switch (permissions) {
> -    case DefinedAtom::permR__:
> -      this->_flags = SHF_ALLOC;
> -      break;
> -    case DefinedAtom::permR_X:
> -      this->_flags = SHF_ALLOC | SHF_EXECINSTR;
> -      break;
> -    case DefinedAtom::permRW_:
> -    case DefinedAtom::permRW_L:
> -      this->_flags = SHF_ALLOC | SHF_WRITE;
> -      if (_contentType == DefinedAtom::typeThreadData ||
> -          _contentType == DefinedAtom::typeThreadZeroFill)
> -        this->_flags |= SHF_TLS;
> -      break;
> -    case DefinedAtom::permRWX:
> -      this->_flags = SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR;
> -      break;
> -    case DefinedAtom::perm___:
> -      this->_flags = 0;
> -      break;
> -    }
> -  }
> +              int32_t contentType, int32_t permissions, int32_t order);
>   
>     /// Align the offset to the required modulus defined by the atom alignment
>     uint64_t alignOffset(uint64_t offset, DefinedAtom::Alignment &atomAlign);
> @@ -231,29 +161,16 @@ public:
>     /// \brief Set the virtual address of each Atom in the Section. This
>     /// routine gets called after the linker fixes up the virtual address
>     /// of the section
> -  virtual void assignVirtualAddress(uint64_t addr) override {
> -    parallel_for_each(_atoms.begin(), _atoms.end(), [&](AtomLayout *ai) {
> -      ai->_virtualAddr = addr + ai->_fileOffset;
> -    });
> -  }
> +  virtual void assignVirtualAddress(uint64_t addr) override;
>   
>     /// \brief Set the file offset of each Atom in the section. This routine
>     /// gets called after the linker fixes up the section offset
> -  void assignFileOffsets(uint64_t offset) override {
> -    parallel_for_each(_atoms.begin(), _atoms.end(), [&](AtomLayout *ai) {
> -      ai->_fileOffset = offset + ai->_fileOffset;
> -    });
> -  }
> +  void assignFileOffsets(uint64_t offset) override;
>   
>     /// \brief Find the Atom address given a name, this is needed to properly
>     ///  apply relocation. The section class calls this to find the atom address
>     ///  to fix the relocation
> -  const AtomLayout *findAtomLayoutByName(StringRef name) const override {
> -    for (auto ai : _atoms)
> -      if (ai->_atom->name() == name)
> -        return ai;
> -    return nullptr;
> -  }
> +  const AtomLayout *findAtomLayoutByName(StringRef name) const override;
>   
>     /// \brief Return the raw flags, we need this to sort segments
>     int64_t atomflags() const { return _contentPermissions; }
> @@ -279,165 +196,9 @@ protected:
>     mutable std::mutex _outputMutex;
>   
>     void printError(const std::string &errorStr, const AtomLayout &atom,
> -                  const Reference &ref) const {
> -    StringRef kindValStr;
> -    if (!this->_ctx.registry().referenceKindToString(
> -            ref.kindNamespace(), ref.kindArch(), ref.kindValue(), kindValStr)) {
> -      kindValStr = "unknown";
> -    }
> -
> -    std::string errStr = (Twine(errorStr) + " in file " +
> -                          atom._atom->file().path() +
> -                          ": reference from " + atom._atom->name() +
> -                          "+" + Twine(ref.offsetInAtom()) +
> -                          " to " + ref.target()->name() +
> -                          "+" + Twine(ref.addend()) +
> -                          " of type " + Twine(ref.kindValue()) +
> -                          " (" + kindValStr + ")\n").str();
> -
> -    // Take the lock to prevent output getting interleaved between threads
> -    std::lock_guard<std::mutex> lock(_outputMutex);
> -    llvm::errs() << errStr;
> -  }
> +                  const Reference &ref) const;
>   };
>   
> -/// Align the offset to the required modulus defined by the atom alignment
> -template <class ELFT>
> -uint64_t AtomSection<ELFT>::alignOffset(uint64_t offset,
> -                                        DefinedAtom::Alignment &atomAlign) {
> -  uint64_t requiredModulus = atomAlign.modulus;
> -  uint64_t alignment = atomAlign.value;
> -  uint64_t currentModulus = (offset % alignment);
> -  uint64_t retOffset = offset;
> -  if (currentModulus != requiredModulus) {
> -    if (requiredModulus > currentModulus)
> -      retOffset += requiredModulus - currentModulus;
> -    else
> -      retOffset += alignment + requiredModulus - currentModulus;
> -  }
> -  return retOffset;
> -}
> -
> -// \brief Append an atom to a Section. The atom gets pushed into a vector
> -// contains the atom, the atom file offset, the atom virtual address
> -// the atom file offset is aligned appropriately as set by the Reader
> -template <class ELFT>
> -const lld::AtomLayout *AtomSection<ELFT>::appendAtom(const Atom *atom) {
> -  const DefinedAtom *definedAtom = cast<DefinedAtom>(atom);
> -
> -  DefinedAtom::Alignment atomAlign = definedAtom->alignment();
> -  uint64_t alignment = atomAlign.value;
> -  // Align the atom to the required modulus/ align the file offset and the
> -  // memory offset separately this is required so that BSS symbols are handled
> -  // properly as the BSS symbols only occupy memory size and not file size
> -  uint64_t fOffset = alignOffset(this->fileSize(), atomAlign);
> -  uint64_t mOffset = alignOffset(this->memSize(), atomAlign);
> -  switch(definedAtom->contentType()) {
> -  case DefinedAtom::typeCode:
> -  case DefinedAtom::typeConstant:
> -  case DefinedAtom::typeData:
> -  case DefinedAtom::typeDataFast:
> -  case DefinedAtom::typeZeroFillFast:
> -  case DefinedAtom::typeGOT:
> -  case DefinedAtom::typeStub:
> -  case DefinedAtom::typeResolver:
> -  case DefinedAtom::typeThreadData:
> -  case DefinedAtom::typeRONote:
> -  case DefinedAtom::typeRWNote:
> -    _atoms.push_back(new (_alloc) lld::AtomLayout(atom, fOffset, 0));
> -    this->_fsize = fOffset + definedAtom->size();
> -    this->_msize = mOffset + definedAtom->size();
> -    DEBUG_WITH_TYPE("Section",
> -                    llvm::dbgs() << "[" << this->name() << " " << this << "] "
> -                                 << "Adding atom: " << atom->name() << "@"
> -                                 << fOffset << "\n");
> -    break;
> -  case DefinedAtom::typeNoAlloc:
> -    _atoms.push_back(new (_alloc) lld::AtomLayout(atom, fOffset, 0));
> -    this->_fsize = fOffset + definedAtom->size();
> -    DEBUG_WITH_TYPE("Section", llvm::dbgs() << "[" << this->name() << " "
> -                                            << this << "] "
> -                                            << "Adding atom: " << atom->name()
> -                                            << "@" << fOffset << "\n");
> -    break;
> -  case DefinedAtom::typeThreadZeroFill:
> -  case DefinedAtom::typeZeroFill:
> -    _atoms.push_back(new (_alloc) lld::AtomLayout(atom, mOffset, 0));
> -    this->_msize = mOffset + definedAtom->size();
> -    break;
> -  default:
> -    llvm::dbgs() << definedAtom->contentType() << "\n";
> -    llvm_unreachable("Uexpected content type.");
> -  }
> -  // Set the section alignment to the largest alignment
> -  // std::max doesn't support uint64_t
> -  if (this->_alignment < alignment)
> -    this->_alignment = alignment;
> -
> -  if (_atoms.size())
> -    return _atoms.back();
> -  return nullptr;
> -}
> -
> -/// \brief convert the segment type to a String for diagnostics
> -///        and printing purposes
> -template <class ELFT> StringRef Section<ELFT>::segmentKindToStr() const {
> -  switch(_segmentType) {
> -  case llvm::ELF::PT_DYNAMIC:
> -    return "DYNAMIC";
> -  case llvm::ELF::PT_INTERP:
> -    return "INTERP";
> -  case llvm::ELF::PT_LOAD:
> -    return "LOAD";
> -  case llvm::ELF::PT_GNU_EH_FRAME:
> -    return "EH_FRAME";
> -  case llvm::ELF::PT_GNU_RELRO:
> -    return "GNU_RELRO";
> -  case llvm::ELF::PT_NOTE:
> -    return "NOTE";
> -  case llvm::ELF::PT_NULL:
> -    return "NULL";
> -  case llvm::ELF::PT_TLS:
> -    return "TLS";
> -  default:
> -    return "UNKNOWN";
> -  }
> -}
> -
> -/// \brief Write the section and the atom contents to the buffer
> -template <class ELFT>
> -void AtomSection<ELFT>::write(ELFWriter *writer, TargetLayout<ELFT> &layout,
> -                              llvm::FileOutputBuffer &buffer) {
> -  uint8_t *chunkBuffer = buffer.getBufferStart();
> -  bool success = true;
> -  parallel_for_each(_atoms.begin(), _atoms.end(), [&](lld::AtomLayout * ai) {
> -    DEBUG_WITH_TYPE("Section",
> -                    llvm::dbgs() << "Writing atom: " << ai->_atom->name()
> -                                 << " | " << ai->_fileOffset << "\n");
> -    const DefinedAtom *definedAtom = cast<DefinedAtom>(ai->_atom);
> -    if (!definedAtom->occupiesDiskSpace())
> -      return;
> -    // Copy raw content of atom to file buffer.
> -    ArrayRef<uint8_t> content = definedAtom->rawContent();
> -    uint64_t contentSize = content.size();
> -    if (contentSize == 0)
> -      return;
> -    uint8_t *atomContent = chunkBuffer + ai->_fileOffset;
> -    std::memcpy(atomContent, content.data(), contentSize);
> -    const TargetRelocationHandler &relHandler =
> -        this->_ctx.getTargetHandler().getRelocationHandler();
> -    for (const auto ref : *definedAtom) {
> -      if (std::error_code ec = relHandler.applyRelocation(*writer, buffer,
> -                                                          *ai, *ref)) {
> -        printError(ec.message(), *ai, *ref);
> -        success = false;
> -      }
> -    }
> -  });
> -  if (!success)
> -    llvm::report_fatal_error("relocating output");
> -}
> -
>   /// \brief A OutputSection represents a set of sections grouped by the same
>   /// name. The output file that gets written by the linker has sections grouped
>   /// by similar names
> @@ -480,42 +241,25 @@ public:
>     }
>   
>     void setLink(uint64_t link) { _link = link; }
> -
>     void setInfo(uint64_t info) { _shInfo = info; }
> -
>     void setFlag(uint64_t flags) { _flags = flags; }
> -
>     void setType(int64_t type) { _type = type; }
> -
>     range<ChunkIter> sections() { return _sections; }
>   
>     // The below functions returns the properties of the OutputSection.
>     bool hasSegment() const { return _hasSegment; }
> -
>     StringRef name() const { return _name; }
> -
>     int64_t shinfo() const { return _shInfo; }
> -
>     uint64_t alignment() const { return _alignment; }
> -
>     int64_t link() const { return _link; }
> -
>     int64_t type() const { return _type; }
> -
>     uint64_t virtualAddr() const { return _virtualAddr; }
> -
>     int64_t ordinal() const { return _ordinal; }
> -
>     int64_t kind() const { return _kind; }
> -
>     uint64_t fileSize() const { return _size; }
> -
>     int64_t entsize() const { return _entSize; }
> -
>     uint64_t fileOffset() const { return _fileOffset; }
> -
>     int64_t flags() const { return _flags; }
> -
>     uint64_t memSize() { return _memSize; }
>   
>   private:
> @@ -537,26 +281,8 @@ private:
>     std::vector<Chunk<ELFT> *> _sections;
>   };
>   
> -template <class ELFT> void OutputSection<ELFT>::appendSection(Chunk<ELFT> *c) {
> -  if (c->alignment() > _alignment)
> -    _alignment = c->alignment();
> -  if (const auto section = dyn_cast<Section<ELFT>>(c)) {
> -    assert(!_link && "Section already has a link!");
> -    _link = section->getLink();
> -    _shInfo = section->getInfo();
> -    _entSize = section->getEntSize();
> -    _type = section->getType();
> -    if (_flags < section->getFlags())
> -      _flags = section->getFlags();
> -    section->setOutputSection(this, (_sections.size() == 0));
> -  }
> -  _kind = c->kind();
> -  _sections.push_back(c);
> -}
> -
>   /// \brief The class represents the ELF String Table
> -template<class ELFT>
> -class StringTable : public Section<ELFT> {
> +template <class ELFT> class StringTable : public Section<ELFT> {
>   public:
>     StringTable(const ELFLinkingContext &, const char *str, int32_t order,
>                 bool dynamic = false);
> @@ -581,63 +307,16 @@ private:
>         return lhs.equals(rhs);
>       }
>     };
> -  typedef typename llvm::DenseMap<StringRef, uint64_t,
> -                                  StringRefMappingInfo> StringMapT;
> +  typedef typename llvm::DenseMap<StringRef, uint64_t, StringRefMappingInfo>
> +      StringMapT;
>     typedef typename StringMapT::iterator StringMapTIter;
>     StringMapT _stringMap;
>   };
>   
> -template <class ELFT>
> -StringTable<ELFT>::StringTable(const ELFLinkingContext &ctx, const char *str,
> -                               int32_t order, bool dynamic)
> -    : Section<ELFT>(ctx, str, "StringTable") {
> -  // the string table has a NULL entry for which
> -  // add an empty string
> -  _strings.push_back("");
> -  this->_fsize = 1;
> -  this->_alignment = 1;
> -  this->setOrder(order);
> -  this->_type = SHT_STRTAB;
> -  if (dynamic) {
> -    this->_flags = SHF_ALLOC;
> -    this->_msize = this->_fsize;
> -  }
> -}
> -
> -template <class ELFT> uint64_t StringTable<ELFT>::addString(StringRef symname) {
> -  if (symname.empty())
> -    return 0;
> -  StringMapTIter stringIter = _stringMap.find(symname);
> -  if (stringIter == _stringMap.end()) {
> -    _strings.push_back(symname);
> -    uint64_t offset = this->_fsize;
> -    this->_fsize += symname.size() + 1;
> -    if (this->_flags & SHF_ALLOC)
> -      this->_msize = this->_fsize;
> -    _stringMap[symname] = offset;
> -    return offset;
> -  }
> -  return stringIter->second;
> -}
> -
> -template <class ELFT>
> -void StringTable<ELFT>::write(ELFWriter *writer, TargetLayout<ELFT> &,
> -                              llvm::FileOutputBuffer &buffer) {
> -  uint8_t *chunkBuffer = buffer.getBufferStart();
> -  uint8_t *dest = chunkBuffer + this->fileOffset();
> -  for (auto si : _strings) {
> -    memcpy(dest, si.data(), si.size());
> -    dest += si.size();
> -    memcpy(dest, "", 1);
> -    dest += 1;
> -  }
> -}
> -
>   /// \brief The SymbolTable class represents the symbol table in a ELF file
> -template<class ELFT>
> -class SymbolTable : public Section<ELFT> {
> -  typedef typename llvm::object::ELFDataTypeTypedefHelper<ELFT>::Elf_Addr
> -      Elf_Addr;
> +template <class ELFT> class SymbolTable : public Section<ELFT> {
> +  typedef
> +      typename llvm::object::ELFDataTypeTypedefHelper<ELFT>::Elf_Addr Elf_Addr;
>   
>   public:
>     typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
> @@ -670,9 +349,9 @@ public:
>   
>     virtual void sortSymbols() {
>       std::stable_sort(_symbolTable.begin(), _symbolTable.end(),
> -                     [](const SymbolEntry & A, const SymbolEntry & B) {
> -      return A._symbol.getBinding() < B._symbol.getBinding();
> -    });
> +                     [](const SymbolEntry &A, const SymbolEntry &B) {
> +                       return A._symbol.getBinding() < B._symbol.getBinding();
> +                     });
>     }
>   
>     virtual void addAbsoluteAtom(Elf_Sym &sym, const AbsoluteAtom *aa,
> @@ -710,229 +389,20 @@ protected:
>     std::vector<SymbolEntry> _symbolTable;
>   };
>   
> -/// ELF Symbol Table
> -template <class ELFT>
> -SymbolTable<ELFT>::SymbolTable(const ELFLinkingContext &ctx, const char *str,
> -                               int32_t order)
> -    : Section<ELFT>(ctx, str, "SymbolTable") {
> -  this->setOrder(order);
> -  Elf_Sym symbol;
> -  std::memset(&symbol, 0, sizeof(Elf_Sym));
> -  _symbolTable.push_back(SymbolEntry(nullptr, symbol, nullptr));
> -  this->_entSize = sizeof(Elf_Sym);
> -  this->_fsize = sizeof(Elf_Sym);
> -  this->_alignment = sizeof(Elf_Addr);
> -  this->_type = SHT_SYMTAB;
> -}
> -
> -template <class ELFT>
> -void SymbolTable<ELFT>::addDefinedAtom(Elf_Sym &sym, const DefinedAtom *da,
> -                                       int64_t addr) {
> -  unsigned char binding = 0, type = 0;
> -  sym.st_size = da->size();
> -  DefinedAtom::ContentType ct;
> -  switch (ct = da->contentType()) {
> -  case DefinedAtom::typeCode:
> -  case DefinedAtom::typeStub:
> -    sym.st_value = addr;
> -    type = llvm::ELF::STT_FUNC;
> -    break;
> -  case DefinedAtom::typeResolver:
> -    sym.st_value = addr;
> -    type = llvm::ELF::STT_GNU_IFUNC;
> -    break;
> -  case DefinedAtom::typeDataFast:
> -  case DefinedAtom::typeData:
> -  case DefinedAtom::typeConstant:
> -    sym.st_value = addr;
> -    type = llvm::ELF::STT_OBJECT;
> -    break;
> -  case DefinedAtom::typeGOT:
> -    sym.st_value = addr;
> -    type = llvm::ELF::STT_NOTYPE;
> -    break;
> -  case DefinedAtom::typeZeroFill:
> -  case DefinedAtom::typeZeroFillFast:
> -    type = llvm::ELF::STT_OBJECT;
> -    sym.st_value = addr;
> -    break;
> -  case DefinedAtom::typeThreadData:
> -  case DefinedAtom::typeThreadZeroFill:
> -    type = llvm::ELF::STT_TLS;
> -    sym.st_value = addr;
> -    break;
> -  default:
> -    type = llvm::ELF::STT_NOTYPE;
> -  }
> -  if (da->customSectionName() == da->name())
> -    type = llvm::ELF::STT_SECTION;
> -
> -  if (da->scope() == DefinedAtom::scopeTranslationUnit)
> -    binding = llvm::ELF::STB_LOCAL;
> -  else
> -    binding = llvm::ELF::STB_GLOBAL;
> -
> -  sym.setBindingAndType(binding, type);
> -}
> -
> -template <class ELFT>
> -void SymbolTable<ELFT>::addAbsoluteAtom(Elf_Sym &sym, const AbsoluteAtom *aa,
> -                                        int64_t addr) {
> -  unsigned char binding = 0, type = 0;
> -  type = llvm::ELF::STT_OBJECT;
> -  sym.st_shndx = llvm::ELF::SHN_ABS;
> -  switch (aa->scope()) {
> -  case AbsoluteAtom::scopeLinkageUnit:
> -    sym.setVisibility(llvm::ELF::STV_HIDDEN);
> -    binding = llvm::ELF::STB_LOCAL;
> -    break;
> -  case AbsoluteAtom::scopeTranslationUnit:
> -    binding = llvm::ELF::STB_LOCAL;
> -    break;
> -  case AbsoluteAtom::scopeGlobal:
> -    binding = llvm::ELF::STB_GLOBAL;
> -    break;
> -  }
> -  sym.st_value = addr;
> -  sym.setBindingAndType(binding, type);
> -}
> -
> -template <class ELFT>
> -void SymbolTable<ELFT>::addSharedLibAtom(Elf_Sym &sym,
> -                                         const SharedLibraryAtom *aa) {
> -  unsigned char binding = 0, type = 0;
> -  if (aa->type() == SharedLibraryAtom::Type::Data) {
> -    type = llvm::ELF::STT_OBJECT;
> -    sym.st_size = aa->size();
> -  } else
> -    type = llvm::ELF::STT_FUNC;
> -  sym.st_shndx = llvm::ELF::SHN_UNDEF;
> -  binding = llvm::ELF::STB_GLOBAL;
> -  sym.setBindingAndType(binding, type);
> -}
> -
> -template <class ELFT>
> -void SymbolTable<ELFT>::addUndefinedAtom(Elf_Sym &sym,
> -                                         const UndefinedAtom *ua) {
> -  unsigned char binding = 0, type = 0;
> -  sym.st_value = 0;
> -  type = llvm::ELF::STT_NOTYPE;
> -  if (ua->canBeNull())
> -    binding = llvm::ELF::STB_WEAK;
> -  else
> -    binding = llvm::ELF::STB_GLOBAL;
> -  sym.setBindingAndType(binding, type);
> -}
> -
> -/// Add a symbol to the symbol Table, definedAtoms which get added to the symbol
> -/// section don't have their virtual addresses set at the time of adding the
> -/// symbol to the symbol table(Example: dynamic symbols), the addresses needs
> -/// to be updated in the table before writing the dynamic symbol table
> -/// information
> -template <class ELFT>
> -void SymbolTable<ELFT>::addSymbol(const Atom *atom, int32_t sectionIndex,
> -                                  uint64_t addr,
> -                                  const lld::AtomLayout *atomLayout) {
> -  Elf_Sym symbol;
> -
> -  if (atom->name().empty())
> -    return;
> -
> -  symbol.st_name = _stringSection->addString(atom->name());
> -  symbol.st_size = 0;
> -  symbol.st_shndx = sectionIndex;
> -  symbol.st_value = 0;
> -  symbol.st_other = 0;
> -  symbol.setVisibility(llvm::ELF::STV_DEFAULT);
> -
> -  // Add all the atoms
> -  if (const DefinedAtom *da = dyn_cast<const DefinedAtom>(atom))
> -    addDefinedAtom(symbol, da, addr);
> -  else if (const AbsoluteAtom *aa = dyn_cast<const AbsoluteAtom>(atom))
> -    addAbsoluteAtom(symbol, aa, addr);
> -  else if (isa<const SharedLibraryAtom>(atom))
> -    addSharedLibAtom(symbol, dyn_cast<SharedLibraryAtom>(atom));
> -  else
> -    addUndefinedAtom(symbol, dyn_cast<UndefinedAtom>(atom));
> -
> -  _symbolTable.push_back(SymbolEntry(atom, symbol, atomLayout));
> -  this->_fsize += sizeof(Elf_Sym);
> -  if (this->_flags & SHF_ALLOC)
> -    this->_msize = this->_fsize;
> -}
> -
> -template <class ELFT> void SymbolTable<ELFT>::finalize(bool sort) {
> -  // sh_info should be one greater than last symbol with STB_LOCAL binding
> -  // we sort the symbol table to keep all local symbols at the beginning
> -  if (sort)
> -    sortSymbols();
> -
> -  uint16_t shInfo = 0;
> -  for (const auto &i : _symbolTable) {
> -    if (i._symbol.getBinding() != llvm::ELF::STB_LOCAL)
> -      break;
> -    shInfo++;
> -  }
> -  this->_info = shInfo;
> -  this->_link = _stringSection->ordinal();
> -  if (this->_outputSection) {
> -    this->_outputSection->setInfo(this->_info);
> -    this->_outputSection->setLink(this->_link);
> -  }
> -}
> -
> -template <class ELFT>
> -void SymbolTable<ELFT>::write(ELFWriter *writer, TargetLayout<ELFT> &,
> -                              llvm::FileOutputBuffer &buffer) {
> -  uint8_t *chunkBuffer = buffer.getBufferStart();
> -  uint8_t *dest = chunkBuffer + this->fileOffset();
> -  for (const auto &sti : _symbolTable) {
> -    memcpy(dest, &sti._symbol, sizeof(Elf_Sym));
> -    dest += sizeof(Elf_Sym);
> -  }
> -}
> -
>   template <class ELFT> class HashSection;
>   
>   template <class ELFT> class DynamicSymbolTable : public SymbolTable<ELFT> {
>   public:
>     DynamicSymbolTable(const ELFLinkingContext &ctx, TargetLayout<ELFT> &layout,
> -                     const char *str, int32_t order)
> -      : SymbolTable<ELFT>(ctx, str, order), _layout(layout) {
> -    this->_type = SHT_DYNSYM;
> -    this->_flags = SHF_ALLOC;
> -    this->_msize = this->_fsize;
> -  }
> +                     const char *str, int32_t order);
>   
>     // Set the dynamic hash table for symbols to be added into
>     void setHashTable(HashSection<ELFT> *hashTable) { _hashTable = hashTable; }
>   
>     // Add all the dynamic symbos to the hash table
> -  void addSymbolsToHashTable() {
> -    int index = 0;
> -    for (auto &ste : this->_symbolTable) {
> -      if (!ste._atom)
> -        _hashTable->addSymbol("", index);
> -      else
> -        _hashTable->addSymbol(ste._atom->name(), index);
> -      ++index;
> -    }
> -  }
> -
> -  void finalize() override {
> -    // Defined symbols which have been added into the dynamic symbol table
> -    // don't have their addresses known until addresses have been assigned
> -    // so let's update the symbol values after they have got assigned
> -    for (auto &ste: this->_symbolTable) {
> -      const lld::AtomLayout *atomLayout = ste._atomLayout;
> -      if (!atomLayout)
> -        continue;
> -      ste._symbol.st_value = atomLayout->_virtualAddr;
> -    }
> +  void addSymbolsToHashTable();
>   
> -    // Don't sort the symbols
> -    SymbolTable<ELFT>::finalize(false);
> -  }
> +  void finalize() override;
>   
>   protected:
>     HashSection<ELFT> *_hashTable = nullptr;
> @@ -944,117 +414,36 @@ public:
>     typedef llvm::object::Elf_Rel_Impl<ELFT, false> Elf_Rel;
>     typedef llvm::object::Elf_Rel_Impl<ELFT, true> Elf_Rela;
>   
> -  RelocationTable(const ELFLinkingContext &ctx, StringRef str, int32_t order)
> -      : Section<ELFT>(ctx, str, "RelocationTable") {
> -    this->setOrder(order);
> -    this->_flags = SHF_ALLOC;
> -    // Set the alignment properly depending on the target architecture
> -    this->_alignment = ELFT::Is64Bits ? 8 : 4;
> -    if (ctx.isRelaOutputFormat()) {
> -      this->_entSize = sizeof(Elf_Rela);
> -      this->_type = SHT_RELA;
> -    } else {
> -      this->_entSize = sizeof(Elf_Rel);
> -      this->_type = SHT_REL;
> -    }
> -  }
> +  RelocationTable(const ELFLinkingContext &ctx, StringRef str, int32_t order);
>   
>     /// \returns the index of the relocation added.
> -  uint32_t addRelocation(const DefinedAtom &da, const Reference &r) {
> -    _relocs.emplace_back(&da, &r);
> -    this->_fsize = _relocs.size() * this->_entSize;
> -    this->_msize = this->_fsize;
> -    return _relocs.size() - 1;
> -  }
> +  uint32_t addRelocation(const DefinedAtom &da, const Reference &r);
>   
> -  bool getRelocationIndex(const Reference &r, uint32_t &res) {
> -    auto rel = std::find_if(
> -        _relocs.begin(), _relocs.end(),
> -        [&](const std::pair<const DefinedAtom *, const Reference *> &p) {
> -      if (p.second == &r)
> -        return true;
> -      return false;
> -    });
> -    if (rel == _relocs.end())
> -      return false;
> -    res = std::distance(_relocs.begin(), rel);
> -    return true;
> -  }
> +  bool getRelocationIndex(const Reference &r, uint32_t &res);
>   
>     void setSymbolTable(const DynamicSymbolTable<ELFT> *symbolTable) {
>       _symbolTable = symbolTable;
>     }
>   
>     /// \brief Check if any relocation modifies a read-only section.
> -  bool canModifyReadonlySection() const {
> -    for (const auto &rel : _relocs) {
> -      const DefinedAtom *atom = rel.first;
> -      if ((atom->permissions() & DefinedAtom::permRW_) != DefinedAtom::permRW_)
> -        return true;
> -    }
> -    return false;
> -  }
> +  bool canModifyReadonlySection() const;
>   
> -  void finalize() override {
> -    this->_link = _symbolTable ? _symbolTable->ordinal() : 0;
> -    if (this->_outputSection)
> -      this->_outputSection->setLink(this->_link);
> -  }
> +  void finalize() override;
>   
>     void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
> -             llvm::FileOutputBuffer &buffer) override {
> -    uint8_t *chunkBuffer = buffer.getBufferStart();
> -    uint8_t *dest = chunkBuffer + this->fileOffset();
> -    for (const auto &rel : _relocs) {
> -      if (this->_ctx.isRelaOutputFormat()) {
> -        auto &r = *reinterpret_cast<Elf_Rela *>(dest);
> -        writeRela(writer, r, *rel.first, *rel.second);
> -        DEBUG_WITH_TYPE("ELFRelocationTable",
> -                        llvm::dbgs()
> -                            << rel.second->kindValue() << " relocation at "
> -                            << rel.first->name() << "@" << r.r_offset << " to "
> -                            << rel.second->target()->name() << "@" << r.r_addend
> -                            << "\n";);
> -      } else {
> -        auto &r = *reinterpret_cast<Elf_Rel *>(dest);
> -        writeRel(writer, r, *rel.first, *rel.second);
> -        DEBUG_WITH_TYPE("ELFRelocationTable",
> -                        llvm::dbgs() << rel.second->kindValue()
> -                                     << " relocation at " << rel.first->name()
> -                                     << "@" << r.r_offset << " to "
> -                                     << rel.second->target()->name() << "\n";);
> -      }
> -      dest += this->_entSize;
> -    }
> -  }
> +             llvm::FileOutputBuffer &buffer) override;
>   
>   protected:
>     const DynamicSymbolTable<ELFT> *_symbolTable = nullptr;
>   
>     virtual void writeRela(ELFWriter *writer, Elf_Rela &r,
> -                         const DefinedAtom &atom, const Reference &ref) {
> -    r.setSymbolAndType(getSymbolIndex(ref.target()), ref.kindValue(), false);
> -    r.r_offset = writer->addressOfAtom(&atom) + ref.offsetInAtom();
> -    // The addend is used only by relative relocations
> -    if (this->_ctx.isRelativeReloc(ref))
> -      r.r_addend = writer->addressOfAtom(ref.target()) + ref.addend();
> -    else
> -      r.r_addend = 0;
> -  }
> -
> +                         const DefinedAtom &atom, const Reference &ref);
>     virtual void writeRel(ELFWriter *writer, Elf_Rel &r, const DefinedAtom &atom,
> -                        const Reference &ref) {
> -    r.setSymbolAndType(getSymbolIndex(ref.target()), ref.kindValue(), false);
> -    r.r_offset = writer->addressOfAtom(&atom) + ref.offsetInAtom();
> -  }
> -
> -  uint32_t getSymbolIndex(const Atom *a) {
> -    return _symbolTable ? _symbolTable->getSymbolTableIndex(a)
> -                        : (uint32_t)STN_UNDEF;
> -  }
> +                        const Reference &ref);
> +  uint32_t getSymbolIndex(const Atom *a);
>   
>   private:
> -  std::vector<std::pair<const DefinedAtom *, const Reference *> > _relocs;
> +  std::vector<std::pair<const DefinedAtom *, const Reference *>> _relocs;
>   };
>   
>   template <class ELFT> class HashSection;
> @@ -1065,124 +454,24 @@ public:
>     typedef std::vector<Elf_Dyn> EntriesT;
>   
>     DynamicTable(const ELFLinkingContext &ctx, TargetLayout<ELFT> &layout,
> -               StringRef str, int32_t order)
> -      : Section<ELFT>(ctx, str, "DynamicSection"), _layout(layout) {
> -    this->setOrder(order);
> -    this->_entSize = sizeof(Elf_Dyn);
> -    this->_alignment = ELFT::Is64Bits ? 8 : 4;
> -    // Reserve space for the DT_NULL entry.
> -    this->_fsize = sizeof(Elf_Dyn);
> -    this->_msize = sizeof(Elf_Dyn);
> -    this->_type = SHT_DYNAMIC;
> -    this->_flags = SHF_ALLOC;
> -  }
> +               StringRef str, int32_t order);
>   
>     range<typename EntriesT::iterator> entries() { return _entries; }
>   
>     /// \returns the index of the entry.
> -  std::size_t addEntry(Elf_Dyn e) {
> -    _entries.push_back(e);
> -    this->_fsize = (_entries.size() * sizeof(Elf_Dyn)) + sizeof(Elf_Dyn);
> -    this->_msize = this->_fsize;
> -    return _entries.size() - 1;
> -  }
> +  std::size_t addEntry(Elf_Dyn e);
>   
>     void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
> -             llvm::FileOutputBuffer &buffer) override {
> -    uint8_t *chunkBuffer = buffer.getBufferStart();
> -    uint8_t *dest = chunkBuffer + this->fileOffset();
> -    // Add the null entry.
> -    Elf_Dyn d;
> -    d.d_tag = 0;
> -    d.d_un.d_val = 0;
> -    _entries.push_back(d);
> -    std::memcpy(dest, _entries.data(), this->_fsize);
> -  }
> -
> -  virtual void createDefaultEntries() {
> -    bool isRela = this->_ctx.isRelaOutputFormat();
> -
> -    Elf_Dyn dyn;
> -    dyn.d_un.d_val = 0;
> -
> -    dyn.d_tag = DT_HASH;
> -    _dt_hash = addEntry(dyn);
> -    dyn.d_tag = DT_STRTAB;
> -    _dt_strtab = addEntry(dyn);
> -    dyn.d_tag = DT_SYMTAB;
> -    _dt_symtab = addEntry(dyn);
> -    dyn.d_tag = DT_STRSZ;
> -    _dt_strsz = addEntry(dyn);
> -    dyn.d_tag = DT_SYMENT;
> -    _dt_syment = addEntry(dyn);
> -    if (_layout.hasDynamicRelocationTable()) {
> -      dyn.d_tag = isRela ? DT_RELA : DT_REL;
> -      _dt_rela = addEntry(dyn);
> -      dyn.d_tag = isRela ? DT_RELASZ : DT_RELSZ;
> -      _dt_relasz = addEntry(dyn);
> -      dyn.d_tag = isRela ? DT_RELAENT : DT_RELENT;
> -      _dt_relaent = addEntry(dyn);
> -
> -      if (_layout.getDynamicRelocationTable()->canModifyReadonlySection()) {
> -        dyn.d_tag = DT_TEXTREL;
> -        _dt_textrel = addEntry(dyn);
> -      }
> -    }
> -    if (_layout.hasPLTRelocationTable()) {
> -      dyn.d_tag = DT_PLTRELSZ;
> -      _dt_pltrelsz = addEntry(dyn);
> -      dyn.d_tag = getGotPltTag();
> -      _dt_pltgot = addEntry(dyn);
> -      dyn.d_tag = DT_PLTREL;
> -      dyn.d_un.d_val = isRela ? DT_RELA : DT_REL;
> -      _dt_pltrel = addEntry(dyn);
> -      dyn.d_un.d_val = 0;
> -      dyn.d_tag = DT_JMPREL;
> -      _dt_jmprel = addEntry(dyn);
> -    }
> -  }
> +             llvm::FileOutputBuffer &buffer) override;
>   
> -  void doPreFlight() override {
> -    Elf_Dyn dyn;
> -    dyn.d_un.d_val = 0;
> -    auto initArray = _layout.findOutputSection(".init_array");
> -    auto finiArray = _layout.findOutputSection(".fini_array");
> -    if (initArray) {
> -      dyn.d_tag = DT_INIT_ARRAY;
> -      _dt_init_array = addEntry(dyn);
> -      dyn.d_tag = DT_INIT_ARRAYSZ;
> -      _dt_init_arraysz = addEntry(dyn);
> -    }
> -    if (finiArray) {
> -      dyn.d_tag = DT_FINI_ARRAY;
> -      _dt_fini_array = addEntry(dyn);
> -      dyn.d_tag = DT_FINI_ARRAYSZ;
> -      _dt_fini_arraysz = addEntry(dyn);
> -    }
> -    if (getInitAtomLayout()) {
> -      dyn.d_tag = DT_INIT;
> -      _dt_init = addEntry(dyn);
> -    }
> -    if (getFiniAtomLayout()) {
> -      dyn.d_tag = DT_FINI;
> -      _dt_fini = addEntry(dyn);
> -    }
> -  }
> +  virtual void createDefaultEntries();
> +  void doPreFlight() override;
>   
>     /// \brief Dynamic table tag for .got.plt section referencing.
>     /// Usually but not always targets use DT_PLTGOT for that.
>     virtual int64_t getGotPltTag() { return DT_PLTGOT; }
>   
> -  void finalize() override {
> -    StringTable<ELFT> *dynamicStringTable =
> -        _dynamicSymbolTable->getStringTable();
> -    this->_link = dynamicStringTable->ordinal();
> -    if (this->_outputSection) {
> -      this->_outputSection->setType(this->_type);
> -      this->_outputSection->setInfo(this->_info);
> -      this->_outputSection->setLink(this->_link);
> -    }
> -  }
> +  void finalize() override;
>   
>     void setSymbolTable(DynamicSymbolTable<ELFT> *dynsym) {
>       _dynamicSymbolTable = dynsym;
> @@ -1194,42 +483,7 @@ public:
>   
>     void setHashTable(HashSection<ELFT> *hsh) { _hashTable = hsh; }
>   
> -  virtual void updateDynamicTable() {
> -    StringTable<ELFT> *dynamicStringTable =
> -        _dynamicSymbolTable->getStringTable();
> -    _entries[_dt_hash].d_un.d_val = _hashTable->virtualAddr();
> -    _entries[_dt_strtab].d_un.d_val = dynamicStringTable->virtualAddr();
> -    _entries[_dt_symtab].d_un.d_val = _dynamicSymbolTable->virtualAddr();
> -    _entries[_dt_strsz].d_un.d_val = dynamicStringTable->memSize();
> -    _entries[_dt_syment].d_un.d_val = _dynamicSymbolTable->getEntSize();
> -    auto initArray = _layout.findOutputSection(".init_array");
> -    if (initArray) {
> -      _entries[_dt_init_array].d_un.d_val = initArray->virtualAddr();
> -      _entries[_dt_init_arraysz].d_un.d_val = initArray->memSize();
> -    }
> -    auto finiArray = _layout.findOutputSection(".fini_array");
> -    if (finiArray) {
> -      _entries[_dt_fini_array].d_un.d_val = finiArray->virtualAddr();
> -      _entries[_dt_fini_arraysz].d_un.d_val = finiArray->memSize();
> -    }
> -    if (const auto *al = getInitAtomLayout())
> -      _entries[_dt_init].d_un.d_val = getAtomVirtualAddress(al);
> -    if (const auto *al = getFiniAtomLayout())
> -      _entries[_dt_fini].d_un.d_val = getAtomVirtualAddress(al);
> -    if (_layout.hasDynamicRelocationTable()) {
> -      auto relaTbl = _layout.getDynamicRelocationTable();
> -      _entries[_dt_rela].d_un.d_val = relaTbl->virtualAddr();
> -      _entries[_dt_relasz].d_un.d_val = relaTbl->memSize();
> -      _entries[_dt_relaent].d_un.d_val = relaTbl->getEntSize();
> -    }
> -    if (_layout.hasPLTRelocationTable()) {
> -      auto relaTbl = _layout.getPLTRelocationTable();
> -      _entries[_dt_jmprel].d_un.d_val = relaTbl->virtualAddr();
> -      _entries[_dt_pltrelsz].d_un.d_val = relaTbl->memSize();
> -      auto gotplt = _layout.findOutputSection(".got.plt");
> -      _entries[_dt_pltgot].d_un.d_val = gotplt->virtualAddr();
> -    }
> -  }
> +  virtual void updateDynamicTable();
>   
>   protected:
>     EntriesT _entries;
> @@ -1266,41 +520,18 @@ private:
>     DynamicSymbolTable<ELFT> *_dynamicSymbolTable;
>     HashSection<ELFT> *_hashTable;
>   
> -  const AtomLayout *getInitAtomLayout() {
> -    auto al = _layout.findAtomLayoutByName(this->_ctx.initFunction());
> -    if (al && isa<DefinedAtom>(al->_atom))
> -      return al;
> -    return nullptr;
> -  }
> +  const AtomLayout *getInitAtomLayout();
>   
> -  const AtomLayout *getFiniAtomLayout() {
> -    auto al = _layout.findAtomLayoutByName(this->_ctx.finiFunction());
> -    if (al && isa<DefinedAtom>(al->_atom))
> -      return al;
> -    return nullptr;
> -  }
> +  const AtomLayout *getFiniAtomLayout();
>   };
>   
>   template <class ELFT> class InterpSection : public Section<ELFT> {
>   public:
>     InterpSection(const ELFLinkingContext &ctx, StringRef str, int32_t order,
> -                StringRef interp)
> -      : Section<ELFT>(ctx, str, "Dynamic:Interp"), _interp(interp) {
> -    this->setOrder(order);
> -    this->_alignment = 1;
> -    // + 1 for null term.
> -    this->_fsize = interp.size() + 1;
> -    this->_msize = this->_fsize;
> -    this->_type = SHT_PROGBITS;
> -    this->_flags = SHF_ALLOC;
> -  }
> +                StringRef interp);
>   
>     void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
> -             llvm::FileOutputBuffer &buffer) {
> -    uint8_t *chunkBuffer = buffer.getBufferStart();
> -    uint8_t *dest = chunkBuffer + this->fileOffset();
> -    std::memcpy(dest, _interp.data(), _interp.size());
> -  }
> +             llvm::FileOutputBuffer &buffer);
>   
>   private:
>     StringRef _interp;
> @@ -1325,7 +556,6 @@ private:
>   ///  * Take the value from the buckets[hash % nbuckets] as the index of symbol
>   ///  * Compare the symbol's name, if true return, if false, look through the
>   ///  * array since there was a collision
> -
>   template <class ELFT> class HashSection : public Section<ELFT> {
>     struct SymbolTableEntry {
>       StringRef _name;
> @@ -1333,92 +563,25 @@ template <class ELFT> class HashSection
>     };
>   
>   public:
> -  HashSection(const ELFLinkingContext &ctx, StringRef name, int32_t order)
> -      : Section<ELFT>(ctx, name, "Dynamic:Hash") {
> -    this->setOrder(order);
> -    this->_entSize = 4;
> -    this->_type = SHT_HASH;
> -    this->_flags = SHF_ALLOC;
> -    this->_alignment = ELFT::Is64Bits ? 8 : 4;
> -    this->_fsize = 0;
> -    this->_msize = 0;
> -  }
> +  HashSection(const ELFLinkingContext &ctx, StringRef name, int32_t order);
>   
>     /// \brief add the dynamic symbol into the table so that the
>     /// hash could be calculated
> -  void addSymbol(StringRef name, uint32_t index) {
> -    SymbolTableEntry ste;
> -    ste._name = name;
> -    ste._index = index;
> -    _entries.push_back(ste);
> -  }
> +  void addSymbol(StringRef name, uint32_t index);
>   
>     /// \brief Set the dynamic symbol table
> -  void setSymbolTable(const DynamicSymbolTable<ELFT> *symbolTable) {
> -    _symbolTable = symbolTable;
> -  }
> +  void setSymbolTable(const DynamicSymbolTable<ELFT> *symbolTable);
>   
>     // The size of the section has to be determined so that fileoffsets
>     // may be properly assigned. Let's calculate the buckets and the chains
>     // and fill the chains and the buckets hash table used by the dynamic
>     // linker and update the filesize and memory size accordingly
> -  void doPreFlight() override {
> -    // The number of buckets to use for a certain number of symbols.
> -    // If there are less than 3 symbols, 1 bucket will be used. If
> -    // there are less than 17 symbols, 3 buckets will be used, and so
> -    // forth. The bucket numbers are defined by GNU ld. We use the
> -    // same rules here so we generate hash sections with the same
> -    // size as those generated by GNU ld.
> -    uint32_t hashBuckets[] = { 1, 3, 17, 37, 67, 97, 131, 197, 263, 521, 1031,
> -                               2053, 4099, 8209, 16411, 32771, 65537, 131101,
> -                               262147 };
> -    int hashBucketsCount = sizeof(hashBuckets) / sizeof(uint32_t);
> -
> -    unsigned int bucketsCount = 0;
> -    unsigned int dynSymCount = _entries.size();
> -
> -    // Get the number of buckes that we want to use
> -    for (int i = 0; i < hashBucketsCount; ++i) {
> -      if (dynSymCount < hashBuckets[i])
> -        break;
> -      bucketsCount = hashBuckets[i];
> -    }
> -    _buckets.resize(bucketsCount);
> -    _chains.resize(_entries.size());
> +  void doPreFlight() override;
>   
> -    // Create the hash table for the dynamic linker
> -    for (auto ai : _entries) {
> -      unsigned int dynsymIndex = ai._index;
> -      unsigned int bucketpos = llvm::object::elf_hash(ai._name) % bucketsCount;
> -      _chains[dynsymIndex] = _buckets[bucketpos];
> -      _buckets[bucketpos] = dynsymIndex;
> -    }
> -
> -    this->_fsize = (2 + _chains.size() + _buckets.size()) * sizeof(uint32_t);
> -    this->_msize = this->_fsize;
> -  }
> -
> -  void finalize() override {
> -    this->_link = _symbolTable ? _symbolTable->ordinal() : 0;
> -    if (this->_outputSection)
> -      this->_outputSection->setLink(this->_link);
> -  }
> +  void finalize() override;
>   
>     void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
> -             llvm::FileOutputBuffer &buffer) override {
> -    uint8_t *chunkBuffer = buffer.getBufferStart();
> -    uint8_t *dest = chunkBuffer + this->fileOffset();
> -    Elf_Word bucketChainCounts[2];
> -    bucketChainCounts[0] = _buckets.size();
> -    bucketChainCounts[1] = _chains.size();
> -    std::memcpy(dest, bucketChainCounts, sizeof(bucketChainCounts));
> -    dest += sizeof(bucketChainCounts);
> -    // write bucket values
> -    std::memcpy(dest, _buckets.data(), _buckets.size() * sizeof(Elf_Word));
> -    dest += _buckets.size() * sizeof(Elf_Word);
> -    // write chain values
> -    std::memcpy(dest, _chains.data(), _chains.size() * sizeof(Elf_Word));
> -  }
> +             llvm::FileOutputBuffer &buffer) override;
>   
>   private:
>     typedef
> @@ -1433,47 +596,17 @@ private:
>   template <class ELFT> class EHFrameHeader : public Section<ELFT> {
>   public:
>     EHFrameHeader(const ELFLinkingContext &ctx, StringRef name,
> -                TargetLayout<ELFT> &layout, int32_t order)
> -      : Section<ELFT>(ctx, name, "EHFrameHeader"), _layout(layout) {
> -    this->setOrder(order);
> -    this->_entSize = 0;
> -    this->_type = SHT_PROGBITS;
> -    this->_flags = SHF_ALLOC;
> -    this->_alignment = ELFT::Is64Bits ? 8 : 4;
> -    // Minimum size for empty .eh_frame_hdr.
> -    this->_fsize = 1 + 1 + 1 + 1 + 4;
> -    this->_msize = this->_fsize;
> -  }
> -
> -  void doPreFlight() override {
> -    // TODO: Generate a proper binary search table.
> -  }
> -
> -  void finalize() override {
> -    OutputSection<ELFT> *s = _layout.findOutputSection(".eh_frame");
> -    OutputSection<ELFT> *h = _layout.findOutputSection(".eh_frame_hdr");
> -    if (s && h)
> -      _ehFrameOffset = s->virtualAddr() - (h->virtualAddr() + 4);
> -  }
> -
> +                TargetLayout<ELFT> &layout, int32_t order);
> +  void doPreFlight() override;
> +  void finalize() override;
>     void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
> -             llvm::FileOutputBuffer &buffer) override {
> -    uint8_t *chunkBuffer = buffer.getBufferStart();
> -    uint8_t *dest = chunkBuffer + this->fileOffset();
> -    int pos = 0;
> -    dest[pos++] = 1; // version
> -    dest[pos++] = llvm::dwarf::DW_EH_PE_pcrel |
> -                  llvm::dwarf::DW_EH_PE_sdata4; // eh_frame_ptr_enc
> -    dest[pos++] = llvm::dwarf::DW_EH_PE_omit; // fde_count_enc
> -    dest[pos++] = llvm::dwarf::DW_EH_PE_omit; // table_enc
> -    *reinterpret_cast<typename llvm::object::ELFFile<ELFT>::Elf_Sword *>(
> -        dest + pos) = _ehFrameOffset;
> -  }
> +             llvm::FileOutputBuffer &buffer) override;
>   
>   private:
>     int32_t _ehFrameOffset = 0;
>     TargetLayout<ELFT> &_layout;
>   };
> +
>   } // end namespace elf
>   } // end namespace lld
>   
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>


-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by the Linux Foundation




More information about the llvm-commits mailing list