[ELF] Delete empty TargetLayout class and rename DefaultLayout to TargetLayout
authorSimon Atanasyan <simon@atanasyan.com>
Fri, 3 Apr 2015 21:01:07 +0000 (21:01 +0000)
committerSimon Atanasyan <simon@atanasyan.com>
Fri, 3 Apr 2015 21:01:07 +0000 (21:01 +0000)
No functional changes.

llvm-svn: 234052

lld/lib/ReaderWriter/ELF/ARM/ARMSymbolTable.h
lld/lib/ReaderWriter/ELF/DefaultLayout.h [deleted file]
lld/lib/ReaderWriter/ELF/ExecutableWriter.h
lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h
lld/lib/ReaderWriter/ELF/Mips/MipsDynamicTable.h
lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h
lld/lib/ReaderWriter/ELF/OutputELFWriter.h
lld/lib/ReaderWriter/ELF/SegmentChunks.h
lld/lib/ReaderWriter/ELF/TargetLayout.h

index 0655c7f..b0cc49b 100644 (file)
@@ -28,7 +28,7 @@ public:
 template <class ELFT>
 ARMSymbolTable<ELFT>::ARMSymbolTable(const ELFLinkingContext &ctx)
     : SymbolTable<ELFT>(ctx, ".symtab",
-                        DefaultLayout<ELFT>::ORDER_SYMBOL_TABLE) {}
+                        TargetLayout<ELFT>::ORDER_SYMBOL_TABLE) {}
 
 template <class ELFT>
 void ARMSymbolTable<ELFT>::addDefinedAtom(Elf_Sym &sym, const DefinedAtom *da,
diff --git a/lld/lib/ReaderWriter/ELF/DefaultLayout.h b/lld/lib/ReaderWriter/ELF/DefaultLayout.h
deleted file mode 100644 (file)
index 63f537b..0000000
+++ /dev/null
@@ -1,998 +0,0 @@
-//===- lib/ReaderWriter/ELF/DefaultLayout.h -------------------------------===//
-//
-//                             The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_DEFAULT_LAYOUT_H
-#define LLD_READER_WRITER_ELF_DEFAULT_LAYOUT_H
-
-#include "Atoms.h"
-#include "Chunk.h"
-#include "HeaderChunks.h"
-#include "Layout.h"
-#include "SectionChunks.h"
-#include "SegmentChunks.h"
-#include "lld/Core/Instrumentation.h"
-#include "lld/Core/STDExtras.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/DenseSet.h"
-#include "llvm/ADT/Hashing.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/Format.h"
-#include <map>
-#include <unordered_map>
-
-namespace lld {
-namespace elf {
-/// \brief The DefaultLayout class is used by the Writer to arrange
-///        sections and segments in the order determined by the target ELF
-///        format. The writer creates a single instance of the DefaultLayout
-///        class
-template<class ELFT>
-class DefaultLayout : public Layout {
-public:
-
-  // The order in which the sections appear in the output file
-  // If its determined, that the layout needs to change
-  // just changing the order of enumerations would essentially
-  // change the layout in the output file
-  // Change the enumerations so that Target can override and stick
-  // a section anywhere it wants to
-  enum DefaultSectionOrder {
-    ORDER_NOT_DEFINED = 0,
-    ORDER_INTERP = 10,
-    ORDER_RO_NOTE = 15,
-    ORDER_HASH = 30,
-    ORDER_DYNAMIC_SYMBOLS = 40,
-    ORDER_DYNAMIC_STRINGS = 50,
-    ORDER_DYNAMIC_RELOCS = 52,
-    ORDER_DYNAMIC_PLT_RELOCS = 54,
-    ORDER_INIT = 60,
-    ORDER_PLT = 70,
-    ORDER_TEXT = 80,
-    ORDER_FINI = 90,
-    ORDER_REL = 95,
-    ORDER_RODATA = 100,
-    ORDER_EH_FRAME = 110,
-    ORDER_EH_FRAMEHDR = 120,
-    ORDER_TDATA = 124,
-    ORDER_TBSS = 128,
-    ORDER_CTORS = 130,
-    ORDER_DTORS = 140,
-    ORDER_INIT_ARRAY = 150,
-    ORDER_FINI_ARRAY = 160,
-    ORDER_DYNAMIC = 170,
-    ORDER_GOT = 180,
-    ORDER_GOT_PLT = 190,
-    ORDER_DATA = 200,
-    ORDER_RW_NOTE = 205,
-    ORDER_BSS = 210,
-    ORDER_NOALLOC = 215,
-    ORDER_OTHER = 220,
-    ORDER_SECTION_STRINGS = 230,
-    ORDER_SYMBOL_TABLE = 240,
-    ORDER_STRING_TABLE = 250,
-    ORDER_SECTION_HEADERS = 260
-  };
-
-public:
-
-  // The Key used for creating Sections
-  // The sections are created using
-  // SectionName, contentPermissions
-  struct SectionKey {
-    SectionKey(StringRef name, DefinedAtom::ContentPermissions perm,
-               StringRef path)
-        : _name(name), _perm(perm), _path(path) {}
-
-    // Data members
-    StringRef _name;
-    DefinedAtom::ContentPermissions _perm;
-    StringRef _path;
-  };
-
-  struct SectionKeyHash {
-    int64_t operator()(const SectionKey &k) const {
-      return llvm::hash_combine(k._name, k._perm, k._path);
-    }
-  };
-
-  struct SectionKeyEq {
-    bool operator()(const SectionKey &lhs, const SectionKey &rhs) const {
-      return ((lhs._name == rhs._name) && (lhs._perm == rhs._perm) &&
-              (lhs._path == rhs._path));
-    }
-  };
-
-  typedef typename std::vector<Chunk<ELFT> *>::iterator ChunkIter;
-  typedef typename std::vector<Segment<ELFT> *>::iterator SegmentIter;
-
-  // The additional segments are used to figure out
-  // if there is a segment by that type already created
-  // For example : PT_TLS, we have two sections .tdata/.tbss
-  // that are part of PT_TLS, we need to create this additional
-  // segment only once
-  typedef std::pair<int64_t, int64_t> AdditionalSegmentKey;
-  // The segments are created using
-  // SegmentName, Segment flags
-  typedef std::pair<StringRef, int64_t> SegmentKey;
-
-  // HashKey for the Segment
-  class SegmentHashKey {
-  public:
-    int64_t operator() (const SegmentKey &k) const {
-      // k.first = SegmentName
-      // k.second = SegmentFlags
-      return llvm::hash_combine(k.first, k.second);
-    }
-  };
-
-  class AdditionalSegmentHashKey {
-  public:
-    int64_t operator()(const AdditionalSegmentKey &k) const {
-      // k.first = SegmentName
-      // k.second = SegmentFlags
-      return llvm::hash_combine(k.first, k.second);
-    }
-  };
-
-  // Output Sections contain the map of Sectionnames to a vector of sections,
-  // that have been merged to form a single section
-  typedef llvm::StringMap<OutputSection<ELFT> *> OutputSectionMapT;
-  typedef
-      typename std::vector<OutputSection<ELFT> *>::iterator OutputSectionIter;
-
-  typedef std::unordered_map<SectionKey, AtomSection<ELFT> *, SectionKeyHash,
-                             SectionKeyEq> SectionMapT;
-  typedef std::unordered_map<AdditionalSegmentKey, Segment<ELFT> *,
-                             AdditionalSegmentHashKey> AdditionalSegmentMapT;
-  typedef std::unordered_map<SegmentKey, Segment<ELFT> *, SegmentHashKey>
-  SegmentMapT;
-
-  typedef typename std::vector<lld::AtomLayout *>::iterator AbsoluteAtomIterT;
-
-  typedef llvm::DenseSet<const Atom *> AtomSetT;
-
-  DefaultLayout(ELFLinkingContext &ctx)
-      : _ctx(ctx), _linkerScriptSema(ctx.linkerScriptSema()) {}
-
-  /// \brief Return the section order for a input section
-  SectionOrder getSectionOrder(StringRef name, int32_t contentType,
-                               int32_t contentPermissions) override;
-
-  /// \brief Return the name of the input section by decoding the input
-  /// sectionChoice.
-  virtual StringRef getInputSectionName(const DefinedAtom *da) const;
-
-  /// \brief Return the name of the output section from the input section.
-  virtual StringRef getOutputSectionName(StringRef archivePath,
-                                         StringRef memberPath,
-                                         StringRef inputSectionName) const;
-
-  /// \brief Gets or creates a section.
-  AtomSection<ELFT> *
-  getSection(StringRef name, int32_t contentType,
-             DefinedAtom::ContentPermissions contentPermissions,
-             const DefinedAtom *da);
-
-  /// \brief Gets the segment for a output section
-  virtual Layout::SegmentType getSegmentType(Section<ELFT> *section) const;
-
-  /// \brief Returns true/false depending on whether the section has a Output
-  //         segment or not
-  static bool hasOutputSegment(Section<ELFT> *section);
-
-  // Adds an atom to the section
-  ErrorOr<const lld::AtomLayout *> addAtom(const Atom *atom) override;
-
-  /// \brief Find an output Section given a section name.
-  OutputSection<ELFT> *findOutputSection(StringRef name) {
-    auto iter = _outputSectionMap.find(name);
-    if (iter == _outputSectionMap.end())
-      return nullptr;
-    return iter->second;
-  }
-
-  /// \brief find a absolute atom given a name
-  lld::AtomLayout *findAbsoluteAtom(StringRef name) {
-    auto iter = std::find_if(
-        _absoluteAtoms.begin(), _absoluteAtoms.end(),
-        [=](const AtomLayout *a) { return a->_atom->name() == name; });
-    if (iter == _absoluteAtoms.end())
-      return nullptr;
-    return *iter;
-  }
-
-  // Output sections with the same name into a OutputSection
-  void createOutputSections();
-
-  /// \brief Sort the sections by their order as defined by the layout,
-  /// preparing all sections to be assigned to a segment.
-  virtual void sortInputSections();
-
-  /// \brief Add extra chunks to a segment just before including the input
-  /// section given by <archivePath, memberPath, sectionName>. This
-  /// is used to add linker script expressions before each section.
-  virtual void addExtraChunksToSegment(Segment<ELFT> *segment,
-                                       StringRef archivePath,
-                                       StringRef memberPath,
-                                       StringRef sectionName);
-
-  void assignSectionsToSegments() override;
-
-  void assignVirtualAddress() override;
-
-  void assignFileOffsetsForMiscSections();
-
-  range<AbsoluteAtomIterT> absoluteAtoms() { return _absoluteAtoms; }
-
-  void addSection(Chunk<ELFT> *c) { _sections.push_back(c); }
-
-  void finalize() {
-    ScopedTask task(getDefaultDomain(), "Finalize layout");
-    for (auto &si : _sections)
-      si->finalize();
-  }
-
-  void doPreFlight() {
-    for (auto &si : _sections)
-      si->doPreFlight();
-  }
-
-  const AtomLayout *findAtomLayoutByName(StringRef name) const override {
-    for (auto sec : _sections)
-      if (auto section = dyn_cast<Section<ELFT>>(sec))
-        if (auto *al = section->findAtomLayoutByName(name))
-          return al;
-    return nullptr;
-  }
-
-  void setHeader(ELFHeader<ELFT> *elfHeader) { _elfHeader = elfHeader; }
-
-  void setProgramHeader(ProgramHeader<ELFT> *p) {
-    _programHeader = p;
-  }
-
-  range<OutputSectionIter> outputSections() { return _outputSections; }
-
-  range<ChunkIter> sections() { return _sections; }
-
-  range<SegmentIter> segments() { return _segments; }
-
-  ELFHeader<ELFT> *getHeader() { return _elfHeader; }
-
-  bool hasDynamicRelocationTable() const { return !!_dynamicRelocationTable; }
-
-  bool hasPLTRelocationTable() const { return !!_pltRelocationTable; }
-
-  /// \brief Get or create the dynamic relocation table. All relocations in this
-  /// table are processed at startup.
-  RelocationTable<ELFT> *getDynamicRelocationTable() {
-    if (!_dynamicRelocationTable) {
-      _dynamicRelocationTable = std::move(createRelocationTable(
-          _ctx.isRelaOutputFormat() ? ".rela.dyn" : ".rel.dyn",
-          ORDER_DYNAMIC_RELOCS));
-      addSection(_dynamicRelocationTable.get());
-    }
-    return _dynamicRelocationTable.get();
-  }
-
-  /// \brief Get or create the PLT relocation table. Referenced by DT_JMPREL.
-  RelocationTable<ELFT> *getPLTRelocationTable() {
-    if (!_pltRelocationTable) {
-      _pltRelocationTable = std::move(createRelocationTable(
-          _ctx.isRelaOutputFormat() ? ".rela.plt" : ".rel.plt",
-          ORDER_DYNAMIC_PLT_RELOCS));
-      addSection(_pltRelocationTable.get());
-    }
-    return _pltRelocationTable.get();
-  }
-
-  uint64_t getTLSSize() const {
-    for (const auto &phdr : *_programHeader)
-      if (phdr->p_type == llvm::ELF::PT_TLS)
-        return phdr->p_memsz;
-    return 0;
-  }
-
-  bool isReferencedByDefinedAtom(const Atom *a) const {
-    return _referencedDynAtoms.count(a);
-  }
-
-  bool isCopied(const SharedLibraryAtom *sla) const {
-    return _copiedDynSymNames.count(sla->name());
-  }
-
-protected:
-  /// \brief TargetLayouts may use these functions to reorder the input sections
-  /// in a order defined by their ABI.
-  virtual void finalizeOutputSectionLayout() {}
-
-  /// \brief Allocate a new section.
-  virtual AtomSection<ELFT> *createSection(
-      StringRef name, int32_t contentType,
-      DefinedAtom::ContentPermissions contentPermissions,
-      SectionOrder sectionOrder);
-
-  /// \brief Create a new relocation table.
-  virtual unique_bump_ptr<RelocationTable<ELFT>>
-  createRelocationTable(StringRef name, int32_t order) {
-    return unique_bump_ptr<RelocationTable<ELFT>>(
-        new (_allocator) RelocationTable<ELFT>(_ctx, name, order));
-  }
-
-protected:
-  llvm::BumpPtrAllocator _allocator;
-  SectionMapT _sectionMap;
-  OutputSectionMapT _outputSectionMap;
-  AdditionalSegmentMapT _additionalSegmentMap;
-  SegmentMapT _segmentMap;
-  std::vector<Chunk<ELFT> *> _sections;
-  std::vector<Segment<ELFT> *> _segments;
-  std::vector<OutputSection<ELFT> *> _outputSections;
-  ELFHeader<ELFT> *_elfHeader;
-  ProgramHeader<ELFT> *_programHeader;
-  unique_bump_ptr<RelocationTable<ELFT>> _dynamicRelocationTable;
-  unique_bump_ptr<RelocationTable<ELFT>> _pltRelocationTable;
-  std::vector<lld::AtomLayout *> _absoluteAtoms;
-  AtomSetT _referencedDynAtoms;
-  llvm::StringSet<> _copiedDynSymNames;
-  ELFLinkingContext &_ctx;
-  script::Sema &_linkerScriptSema;
-};
-
-template <class ELFT>
-Layout::SectionOrder DefaultLayout<ELFT>::getSectionOrder(
-    StringRef name, int32_t contentType, int32_t contentPermissions) {
-  switch (contentType) {
-  case DefinedAtom::typeResolver:
-  case DefinedAtom::typeCode:
-    return llvm::StringSwitch<Layout::SectionOrder>(name)
-        .StartsWith(".eh_frame_hdr", ORDER_EH_FRAMEHDR)
-        .StartsWith(".eh_frame", ORDER_EH_FRAME)
-        .StartsWith(".init", ORDER_INIT)
-        .StartsWith(".fini", ORDER_FINI)
-        .StartsWith(".hash", ORDER_HASH)
-        .Default(ORDER_TEXT);
-
-  case DefinedAtom::typeConstant:
-    return ORDER_RODATA;
-
-  case DefinedAtom::typeData:
-  case DefinedAtom::typeDataFast:
-    return llvm::StringSwitch<Layout::SectionOrder>(name)
-        .StartsWith(".init_array", ORDER_INIT_ARRAY)
-        .StartsWith(".fini_array", ORDER_FINI_ARRAY)
-        .StartsWith(".dynamic", ORDER_DYNAMIC)
-        .StartsWith(".ctors", ORDER_CTORS)
-        .StartsWith(".dtors", ORDER_DTORS)
-        .Default(ORDER_DATA);
-
-  case DefinedAtom::typeZeroFill:
-  case DefinedAtom::typeZeroFillFast:
-    return ORDER_BSS;
-
-  case DefinedAtom::typeGOT:
-    return llvm::StringSwitch<Layout::SectionOrder>(name)
-        .StartsWith(".got.plt", ORDER_GOT_PLT)
-        .Default(ORDER_GOT);
-
-  case DefinedAtom::typeStub:
-    return ORDER_PLT;
-
-  case DefinedAtom::typeRONote:
-      return ORDER_RO_NOTE;
-
-  case DefinedAtom::typeRWNote:
-      return ORDER_RW_NOTE;
-
-  case DefinedAtom::typeNoAlloc:
-    return ORDER_NOALLOC;
-
-  case DefinedAtom::typeThreadData:
-    return ORDER_TDATA;
-  case DefinedAtom::typeThreadZeroFill:
-    return ORDER_TBSS;
-  default:
-    // If we get passed in a section push it to OTHER
-    if (contentPermissions == DefinedAtom::perm___)
-      return ORDER_OTHER;
-
-    return ORDER_NOT_DEFINED;
-  }
-}
-
-/// \brief This maps the input sections to the output section names
-template <class ELFT>
-StringRef
-DefaultLayout<ELFT>::getInputSectionName(const DefinedAtom *da) const {
-  if (da->sectionChoice() == DefinedAtom::sectionBasedOnContent) {
-    switch (da->contentType()) {
-    case DefinedAtom::typeCode:
-      return ".text";
-    case DefinedAtom::typeData:
-      return ".data";
-    case DefinedAtom::typeConstant:
-      return ".rodata";
-    case DefinedAtom::typeZeroFill:
-      return ".bss";
-    case DefinedAtom::typeThreadData:
-      return ".tdata";
-    case DefinedAtom::typeThreadZeroFill:
-      return ".tbss";
-    default:
-      break;
-    }
-  }
-  return da->customSectionName();
-}
-
-/// \brief This maps the input sections to the output section names.
-template <class ELFT>
-StringRef
-DefaultLayout<ELFT>::getOutputSectionName(StringRef archivePath,
-                                          StringRef memberPath,
-                                          StringRef inputSectionName) const {
-  StringRef outputSectionName;
-  if (_linkerScriptSema.hasLayoutCommands()) {
-    script::Sema::SectionKey key = {archivePath, memberPath, inputSectionName};
-    outputSectionName = _linkerScriptSema.getOutputSection(key);
-    if (!outputSectionName.empty())
-      return outputSectionName;
-  }
-  return llvm::StringSwitch<StringRef>(inputSectionName)
-      .StartsWith(".text", ".text")
-      .StartsWith(".ctors", ".ctors")
-      .StartsWith(".dtors", ".dtors")
-      .StartsWith(".rodata", ".rodata")
-      .StartsWith(".gcc_except_table", ".gcc_except_table")
-      .StartsWith(".data.rel.ro", ".data.rel.ro")
-      .StartsWith(".data.rel.local", ".data.rel.local")
-      .StartsWith(".data", ".data")
-      .StartsWith(".tdata", ".tdata")
-      .StartsWith(".tbss", ".tbss")
-      .StartsWith(".init_array", ".init_array")
-      .StartsWith(".fini_array", ".fini_array")
-      .Default(inputSectionName);
-}
-
-/// \brief Gets the segment for a output section
-template <class ELFT>
-Layout::SegmentType DefaultLayout<ELFT>::getSegmentType(
-    Section<ELFT> *section) const {
-
-  switch (section->order()) {
-  case ORDER_INTERP:
-    return llvm::ELF::PT_INTERP;
-
-  case ORDER_TEXT:
-  case ORDER_HASH:
-  case ORDER_DYNAMIC_SYMBOLS:
-  case ORDER_DYNAMIC_STRINGS:
-  case ORDER_DYNAMIC_RELOCS:
-  case ORDER_DYNAMIC_PLT_RELOCS:
-  case ORDER_REL:
-  case ORDER_INIT:
-  case ORDER_PLT:
-  case ORDER_FINI:
-  case ORDER_RODATA:
-  case ORDER_EH_FRAME:
-  case ORDER_CTORS:
-  case ORDER_DTORS:
-    return llvm::ELF::PT_LOAD;
-
-  case ORDER_RO_NOTE:
-  case ORDER_RW_NOTE:
-    return llvm::ELF::PT_NOTE;
-
-  case ORDER_DYNAMIC:
-    return llvm::ELF::PT_DYNAMIC;
-
-  case ORDER_EH_FRAMEHDR:
-    return llvm::ELF::PT_GNU_EH_FRAME;
-
-  case ORDER_GOT:
-  case ORDER_GOT_PLT:
-  case ORDER_DATA:
-  case ORDER_BSS:
-  case ORDER_INIT_ARRAY:
-  case ORDER_FINI_ARRAY:
-    return llvm::ELF::PT_LOAD;
-
-  case ORDER_TDATA:
-  case ORDER_TBSS:
-    return llvm::ELF::PT_TLS;
-
-  default:
-    return llvm::ELF::PT_NULL;
-  }
-}
-
-template <class ELFT>
-bool DefaultLayout<ELFT>::hasOutputSegment(Section<ELFT> *section) {
-  switch (section->order()) {
-  case ORDER_INTERP:
-  case ORDER_HASH:
-  case ORDER_DYNAMIC_SYMBOLS:
-  case ORDER_DYNAMIC_STRINGS:
-  case ORDER_DYNAMIC_RELOCS:
-  case ORDER_DYNAMIC_PLT_RELOCS:
-  case ORDER_REL:
-  case ORDER_INIT:
-  case ORDER_PLT:
-  case ORDER_TEXT:
-  case ORDER_FINI:
-  case ORDER_RODATA:
-  case ORDER_EH_FRAME:
-  case ORDER_EH_FRAMEHDR:
-  case ORDER_TDATA:
-  case ORDER_TBSS:
-  case ORDER_RO_NOTE:
-  case ORDER_RW_NOTE:
-  case ORDER_DYNAMIC:
-  case ORDER_CTORS:
-  case ORDER_DTORS:
-  case ORDER_GOT:
-  case ORDER_GOT_PLT:
-  case ORDER_DATA:
-  case ORDER_INIT_ARRAY:
-  case ORDER_FINI_ARRAY:
-  case ORDER_BSS:
-  case ORDER_NOALLOC:
-    return true;
-  default:
-    return section->hasOutputSegment();
-  }
-}
-
-template <class ELFT>
-AtomSection<ELFT> *DefaultLayout<ELFT>::createSection(
-    StringRef sectionName, int32_t contentType,
-    DefinedAtom::ContentPermissions permissions, SectionOrder sectionOrder) {
-  return new (_allocator) AtomSection<ELFT>(_ctx, sectionName, contentType,
-                                            permissions, sectionOrder);
-}
-
-template <class ELFT>
-AtomSection<ELFT> *
-DefaultLayout<ELFT>::getSection(StringRef sectionName, int32_t contentType,
-                                DefinedAtom::ContentPermissions permissions,
-                                const DefinedAtom *da) {
-  const SectionKey sectionKey(sectionName, permissions, da->file().path());
-  SectionOrder sectionOrder = getSectionOrder(sectionName, contentType, permissions);
-  auto sec = _sectionMap.find(sectionKey);
-  if (sec != _sectionMap.end())
-    return sec->second;
-  AtomSection<ELFT> *newSec =
-      createSection(sectionName, contentType, permissions, sectionOrder);
-
-  newSec->setOutputSectionName(getOutputSectionName(
-      da->file().archivePath(), da->file().memberPath(), sectionName));
-  newSec->setOrder(sectionOrder);
-  newSec->setArchiveNameOrPath(da->file().archivePath());
-  newSec->setMemberNameOrPath(da->file().memberPath());
-  _sections.push_back(newSec);
-  _sectionMap.insert(std::make_pair(sectionKey, newSec));
-  return newSec;
-}
-
-template <class ELFT>
-ErrorOr<const lld::AtomLayout *>
-DefaultLayout<ELFT>::addAtom(const Atom *atom) {
-  if (const DefinedAtom *definedAtom = dyn_cast<DefinedAtom>(atom)) {
-    // HACK: Ignore undefined atoms. We need to adjust the interface so that
-    // undefined atoms can still be included in the output symbol table for
-    // -noinhibit-exec.
-    if (definedAtom->contentType() == DefinedAtom::typeUnknown)
-      return make_error_code(llvm::errc::invalid_argument);
-    const DefinedAtom::ContentPermissions permissions =
-        definedAtom->permissions();
-    const DefinedAtom::ContentType contentType = definedAtom->contentType();
-
-    StringRef sectionName = getInputSectionName(definedAtom);
-    AtomSection<ELFT> *section =
-        getSection(sectionName, contentType, permissions, definedAtom);
-
-    // Add runtime relocations to the .rela section.
-    for (const auto &reloc : *definedAtom) {
-      bool isLocalReloc = true;
-      if (_ctx.isDynamicRelocation(*reloc)) {
-        getDynamicRelocationTable()->addRelocation(*definedAtom, *reloc);
-        isLocalReloc = false;
-      } else if (_ctx.isPLTRelocation(*reloc)) {
-        getPLTRelocationTable()->addRelocation(*definedAtom, *reloc);
-        isLocalReloc = false;
-      }
-
-      if (!reloc->target())
-        continue;
-
-      //Ignore undefined atoms that are not target of dynamic relocations
-      if (isa<UndefinedAtom>(reloc->target()) && isLocalReloc)
-        continue;
-
-      if (_ctx.isCopyRelocation(*reloc)) {
-        _copiedDynSymNames.insert(definedAtom->name());
-        continue;
-      }
-
-      _referencedDynAtoms.insert(reloc->target());
-    }
-    return section->appendAtom(atom);
-  }
-
-  const AbsoluteAtom *absoluteAtom = cast<AbsoluteAtom>(atom);
-  // Absolute atoms are not part of any section, they are global for the whole
-  // link
-  _absoluteAtoms.push_back(
-      new (_allocator) lld::AtomLayout(absoluteAtom, 0, absoluteAtom->value()));
-  return _absoluteAtoms.back();
-}
-
-/// Output sections with the same name into a OutputSection
-template <class ELFT> void DefaultLayout<ELFT>::createOutputSections() {
-  OutputSection<ELFT> *outputSection;
-
-  for (auto &si : _sections) {
-    Section<ELFT> *section = dyn_cast<Section<ELFT>>(si);
-    if (!section)
-      continue;
-    const std::pair<StringRef, OutputSection<ELFT> *> currentOutputSection(
-        section->outputSectionName(), nullptr);
-    std::pair<typename OutputSectionMapT::iterator, bool> outputSectionInsert(
-        _outputSectionMap.insert(currentOutputSection));
-    if (!outputSectionInsert.second) {
-      outputSection = outputSectionInsert.first->second;
-    } else {
-      outputSection = new (_allocator.Allocate<OutputSection<ELFT>>())
-          OutputSection<ELFT>(section->outputSectionName());
-      _outputSections.push_back(outputSection);
-      outputSectionInsert.first->second = outputSection;
-    }
-    outputSection->appendSection(si);
-  }
-}
-
-template <class ELFT> void DefaultLayout<ELFT>::assignSectionsToSegments() {
-  ScopedTask task(getDefaultDomain(), "assignSectionsToSegments");
-  ELFLinkingContext::OutputMagic outputMagic = _ctx.getOutputMagic();
-  // sort the sections by their order as defined by the layout
-  sortInputSections();
-
-  // Create output sections.
-  createOutputSections();
-
-  // Finalize output section layout.
-  finalizeOutputSectionLayout();
-
-  // Set the ordinal after sorting the sections
-  int ordinal = 1;
-  for (auto osi : _outputSections) {
-    osi->setOrdinal(ordinal);
-    for (auto ai : osi->sections()) {
-      ai->setOrdinal(ordinal);
-    }
-    ++ordinal;
-  }
-  for (auto osi : _outputSections) {
-    for (auto ai : osi->sections()) {
-      if (auto section = dyn_cast<Section<ELFT> >(ai)) {
-        if (!hasOutputSegment(section))
-          continue;
-
-        osi->setLoadableSection(section->isLoadableSection());
-
-        // Get the segment type for the section
-        int64_t segmentType = getSegmentType(section);
-
-        osi->setHasSegment();
-        section->setSegmentType(segmentType);
-        StringRef segmentName = section->segmentKindToStr();
-
-        int64_t lookupSectionFlag = osi->flags();
-        if ((!(lookupSectionFlag & llvm::ELF::SHF_WRITE)) &&
-            (_ctx.mergeRODataToTextSegment()))
-          lookupSectionFlag &= ~llvm::ELF::SHF_EXECINSTR;
-
-        // Merge string sections into Data segment itself
-        lookupSectionFlag &= ~(llvm::ELF::SHF_STRINGS | llvm::ELF::SHF_MERGE);
-
-        // Merge the TLS section into the DATA segment itself
-        lookupSectionFlag &= ~(llvm::ELF::SHF_TLS);
-
-        Segment<ELFT> *segment;
-        // We need a separate segment for sections that don't have
-        // the segment type to be PT_LOAD
-        if (segmentType != llvm::ELF::PT_LOAD) {
-          const AdditionalSegmentKey key(segmentType, lookupSectionFlag);
-          const std::pair<AdditionalSegmentKey, Segment<ELFT> *>
-          additionalSegment(key, nullptr);
-          std::pair<typename AdditionalSegmentMapT::iterator, bool>
-          additionalSegmentInsert(
-              _additionalSegmentMap.insert(additionalSegment));
-          if (!additionalSegmentInsert.second) {
-            segment = additionalSegmentInsert.first->second;
-          } else {
-            segment =
-                new (_allocator) Segment<ELFT>(_ctx, segmentName, segmentType);
-            additionalSegmentInsert.first->second = segment;
-            _segments.push_back(segment);
-          }
-          segment->append(section);
-        }
-        if (segmentType == llvm::ELF::PT_NULL)
-          continue;
-
-        // If the output magic is set to OutputMagic::NMAGIC or
-        // OutputMagic::OMAGIC, Place the data alongside text in one single
-        // segment
-        if (outputMagic == ELFLinkingContext::OutputMagic::NMAGIC ||
-            outputMagic == ELFLinkingContext::OutputMagic::OMAGIC)
-          lookupSectionFlag = llvm::ELF::SHF_EXECINSTR | llvm::ELF::SHF_ALLOC |
-                              llvm::ELF::SHF_WRITE;
-
-        // Use the flags of the merged Section for the segment
-        const SegmentKey key("PT_LOAD", lookupSectionFlag);
-        const std::pair<SegmentKey, Segment<ELFT> *> currentSegment(key,
-                                                                    nullptr);
-        std::pair<typename SegmentMapT::iterator, bool> segmentInsert(
-            _segmentMap.insert(currentSegment));
-        if (!segmentInsert.second) {
-          segment = segmentInsert.first->second;
-        } else {
-          segment = new (_allocator)
-              Segment<ELFT>(_ctx, "PT_LOAD", llvm::ELF::PT_LOAD);
-          segmentInsert.first->second = segment;
-          _segments.push_back(segment);
-        }
-        // Insert chunks with linker script expressions that occur at this
-        // point, just before appending a new input section
-        addExtraChunksToSegment(segment, section->archivePath(),
-                                section->memberPath(),
-                                section->inputSectionName());
-        segment->append(section);
-      }
-    }
-  }
-  if (_ctx.isDynamic() && !_ctx.isDynamicLibrary()) {
-    Segment<ELFT> *segment = new (_allocator) ProgramHeaderSegment<ELFT>(_ctx);
-    _segments.push_back(segment);
-    segment->append(_elfHeader);
-    segment->append(_programHeader);
-  }
-}
-
-template<class ELFT>
-void
-DefaultLayout<ELFT>::assignVirtualAddress() {
-  if (_segments.empty())
-    return;
-
-  std::sort(_segments.begin(), _segments.end(), Segment<ELFT>::compareSegments);
-
-  uint64_t baseAddress = _ctx.getBaseAddress();
-
-  // HACK: This is a super dirty hack. The elf header and program header are
-  // not part of a section, but we need them to be loaded at the base address
-  // so that AT_PHDR is set correctly by the loader and so they are accessible
-  // at runtime. To do this we simply prepend them to the first loadable Segment
-  // and let the layout logic take care of it.
-  Segment<ELFT> *firstLoadSegment = nullptr;
-  for (auto si : _segments) {
-    if (si->segmentType() == llvm::ELF::PT_LOAD) {
-      firstLoadSegment = si;
-      si->firstSection()->setAlign(si->alignment());
-      break;
-    }
-  }
-  assert(firstLoadSegment != nullptr && "No loadable segment!");
-  firstLoadSegment->prepend(_programHeader);
-  firstLoadSegment->prepend(_elfHeader);
-  bool newSegmentHeaderAdded = true;
-  bool virtualAddressAssigned = false;
-  bool fileOffsetAssigned = false;
-  while (true) {
-    for (auto si : _segments) {
-      si->finalize();
-      // Don't add PT_NULL segments into the program header
-      if (si->segmentType() != llvm::ELF::PT_NULL)
-        newSegmentHeaderAdded = _programHeader->addSegment(si);
-    }
-    if (!newSegmentHeaderAdded && virtualAddressAssigned)
-      break;
-    uint64_t address = baseAddress;
-    // start assigning virtual addresses
-    for (auto &si : _segments) {
-      if ((si->segmentType() != llvm::ELF::PT_LOAD) &&
-          (si->segmentType() != llvm::ELF::PT_NULL))
-        continue;
-
-      if (si->segmentType() == llvm::ELF::PT_NULL) {
-        si->assignVirtualAddress(0 /*non loadable*/);
-      } else {
-        if (virtualAddressAssigned && (address != baseAddress) &&
-            (address == si->virtualAddr()))
-          break;
-        si->assignVirtualAddress(address);
-      }
-      address = si->virtualAddr() + si->memSize();
-    }
-    uint64_t baseFileOffset = 0;
-    uint64_t fileoffset = baseFileOffset;
-    for (auto &si : _segments) {
-      if ((si->segmentType() != llvm::ELF::PT_LOAD) &&
-          (si->segmentType() != llvm::ELF::PT_NULL))
-        continue;
-      if (fileOffsetAssigned && (fileoffset != baseFileOffset) &&
-          (fileoffset == si->fileOffset()))
-        break;
-      si->assignFileOffsets(fileoffset);
-      fileoffset = si->fileOffset() + si->fileSize();
-    }
-    virtualAddressAssigned = true;
-    fileOffsetAssigned = true;
-    _programHeader->resetProgramHeaders();
-  }
-  Section<ELFT> *section;
-  // Fix the offsets of all the atoms within a section
-  for (auto &si : _sections) {
-    section = dyn_cast<Section<ELFT>>(si);
-    if (section && DefaultLayout<ELFT>::hasOutputSegment(section))
-      section->assignFileOffsets(section->fileOffset());
-  }
-  // Set the size of the merged Sections
-  for (auto osi : _outputSections) {
-    uint64_t sectionfileoffset = 0;
-    uint64_t startFileOffset = 0;
-    uint64_t sectionsize = 0;
-    bool isFirstSection = true;
-    for (auto si : osi->sections()) {
-      if (isFirstSection) {
-        startFileOffset = si->fileOffset();
-        isFirstSection = false;
-      }
-      sectionfileoffset = si->fileOffset();
-      sectionsize = si->fileSize();
-    }
-    sectionsize = (sectionfileoffset - startFileOffset) + sectionsize;
-    osi->setFileOffset(startFileOffset);
-    osi->setSize(sectionsize);
-  }
-  // Set the virtual addr of the merged Sections
-  for (auto osi : _outputSections) {
-    uint64_t sectionstartaddr = 0;
-    uint64_t startaddr = 0;
-    uint64_t sectionsize = 0;
-    bool isFirstSection = true;
-    for (auto si : osi->sections()) {
-      if (isFirstSection) {
-        startaddr = si->virtualAddr();
-        isFirstSection = false;
-      }
-      sectionstartaddr = si->virtualAddr();
-      sectionsize = si->memSize();
-    }
-    sectionsize = (sectionstartaddr - startaddr) + sectionsize;
-    osi->setMemSize(sectionsize);
-    osi->setAddr(startaddr);
-  }
-}
-
-template <class ELFT>
-void DefaultLayout<ELFT>::assignFileOffsetsForMiscSections() {
-  uint64_t fileoffset = 0;
-  uint64_t size = 0;
-  for (auto si : _segments) {
-    // Don't calculate offsets from non loadable segments
-    if ((si->segmentType() != llvm::ELF::PT_LOAD) &&
-        (si->segmentType() != llvm::ELF::PT_NULL))
-      continue;
-    fileoffset = si->fileOffset();
-    size = si->fileSize();
-  }
-  fileoffset = fileoffset + size;
-  Section<ELFT> *section;
-  for (auto si : _sections) {
-    section = dyn_cast<Section<ELFT>>(si);
-    if (section && DefaultLayout<ELFT>::hasOutputSegment(section))
-      continue;
-    fileoffset = llvm::RoundUpToAlignment(fileoffset, si->alignment());
-    si->setFileOffset(fileoffset);
-    si->setVirtualAddr(0);
-    fileoffset += si->fileSize();
-  }
-}
-
-template <class ELFT> void DefaultLayout<ELFT>::sortInputSections() {
-  // First, sort according to default layout's order
-  std::stable_sort(
-      _sections.begin(), _sections.end(),
-      [](Chunk<ELFT> *A, Chunk<ELFT> *B) { return A->order() < B->order(); });
-
-  if (!_linkerScriptSema.hasLayoutCommands())
-    return;
-
-  // Sort the sections by their order as defined by the linker script
-  std::stable_sort(this->_sections.begin(), this->_sections.end(),
-                   [this](Chunk<ELFT> *A, Chunk<ELFT> *B) {
-                     auto *a = dyn_cast<Section<ELFT>>(A);
-                     auto *b = dyn_cast<Section<ELFT>>(B);
-
-                     if (a == nullptr)
-                       return false;
-                     if (b == nullptr)
-                       return true;
-
-                     return _linkerScriptSema.less(
-                         {a->archivePath(), a->memberPath(),
-                          a->inputSectionName()},
-                         {b->archivePath(), b->memberPath(),
-                          b->inputSectionName()});
-                   });
-  // Now try to arrange sections with no mapping rules to sections with
-  // similar content
-  auto p = this->_sections.begin();
-  // Find first section that has no assigned rule id
-  while (p != this->_sections.end()) {
-    auto *sect = dyn_cast<AtomSection<ELFT>>(*p);
-    if (!sect)
-      break;
-
-    if (!_linkerScriptSema.hasMapping({sect->archivePath(),
-                                       sect->memberPath(),
-                                       sect->inputSectionName()}))
-      break;
-
-    ++p;
-  }
-  // For all sections that have no assigned rule id, try to move them near a
-  // section with similar contents
-  if (p != this->_sections.begin()) {
-    for (; p != this->_sections.end(); ++p) {
-      auto q = p;
-      --q;
-      while (q != this->_sections.begin() &&
-             (*q)->getContentType() != (*p)->getContentType())
-        --q;
-      if ((*q)->getContentType() != (*p)->getContentType())
-        continue;
-      ++q;
-      for (auto i = p; i != q;) {
-        auto next = i--;
-        std::iter_swap(i, next);
-      }
-    }
-  }
-}
-
-template <class ELFT>
-void DefaultLayout<ELFT>::addExtraChunksToSegment(Segment<ELFT> *segment,
-                                                  StringRef archivePath,
-                                                  StringRef memberPath,
-                                                  StringRef sectionName) {
-  if (!_linkerScriptSema.hasLayoutCommands())
-    return;
-
-  std::vector<const script::SymbolAssignment *> exprs =
-      _linkerScriptSema.getExprs({archivePath, memberPath, sectionName});
-  for (auto expr : exprs) {
-    auto expChunk =
-        new (this->_allocator) ExpressionChunk<ELFT>(this->_ctx, expr);
-    segment->append(expChunk);
-  }
-}
-
-} // end namespace elf
-} // end namespace lld
-
-#endif
index b281b09..6fe5baa 100644 (file)
@@ -116,7 +116,7 @@ template <class ELFT> void ExecutableWriter<ELFT>::createDefaultSections() {
   OutputELFWriter<ELFT>::createDefaultSections();
   if (this->_ctx.isDynamic()) {
     _interpSection.reset(new (this->_alloc) InterpSection<ELFT>(
-        this->_ctx, ".interp", DefaultLayout<ELFT>::ORDER_INTERP,
+        this->_ctx, ".interp", TargetLayout<ELFT>::ORDER_INTERP,
         this->_ctx.getInterpreter()));
     this->_layout.addSection(_interpSection.get());
   }
index d4df0e0..facecf5 100644 (file)
@@ -40,8 +40,8 @@ public:
        (contentType == DefinedAtom::typeZeroFillFast))
       return ORDER_SDATA;
 
-    return DefaultLayout<HexagonELFType>::getSectionOrder(name, contentType,
-                                                          contentPermissions);
+    return TargetLayout<HexagonELFType>::getSectionOrder(name, contentType,
+                                                         contentPermissions);
   }
 
   /// \brief Return the appropriate input section name.
@@ -53,7 +53,7 @@ public:
     default:
       break;
     }
-    return DefaultLayout<HexagonELFType>::getInputSectionName(da);
+    return TargetLayout<HexagonELFType>::getInputSectionName(da);
   }
 
   /// \brief Gets or creates a section.
@@ -64,7 +64,7 @@ public:
     if ((contentType == DefinedAtom::typeDataFast) ||
        (contentType == DefinedAtom::typeZeroFillFast))
       return _sdataSection;
-    return DefaultLayout<HexagonELFType>::createSection(
+    return TargetLayout<HexagonELFType>::createSection(
         name, contentType, contentPermissions, sectionOrder);
   }
 
@@ -74,7 +74,7 @@ public:
     if (section->order() == ORDER_SDATA)
       return PT_LOAD;
 
-    return DefaultLayout<HexagonELFType>::getSegmentType(section);
+    return TargetLayout<HexagonELFType>::getSegmentType(section);
   }
 
   Section<HexagonELFType> *getSDataSection() const {
index 0e2bc18..9e667de 100644 (file)
@@ -9,7 +9,7 @@
 #ifndef LLD_READER_WRITER_ELF_MIPS_MIPS_DYNAMIC_TABLE_H
 #define LLD_READER_WRITER_ELF_MIPS_MIPS_DYNAMIC_TABLE_H
 
-#include "DefaultLayout.h"
+#include "TargetLayout.h"
 #include "SectionChunks.h"
 
 namespace lld {
@@ -23,7 +23,7 @@ public:
   MipsDynamicTable(const ELFLinkingContext &ctx,
                    MipsTargetLayout<MipsELFType> &layout)
       : DynamicTable<MipsELFType>(ctx, layout, ".dynamic",
-                                  DefaultLayout<MipsELFType>::ORDER_DYNAMIC),
+                                  TargetLayout<MipsELFType>::ORDER_DYNAMIC),
         _targetLayout(layout) {}
 
   void createDefaultEntries() override {
index 1018e33..cf13889 100644 (file)
@@ -39,7 +39,7 @@ public:
       return _gotSection;
     if (type == DefinedAtom::typeStub && name == ".plt")
       return _pltSection;
-    return DefaultLayout<ELFT>::createSection(name, type, permissions, order);
+    return TargetLayout<ELFT>::createSection(name, type, permissions, order);
   }
 
   /// \brief GP offset relative to .got section.
@@ -63,10 +63,10 @@ public:
   Layout::SectionOrder getSectionOrder(StringRef name, int32_t contentType,
                                        int32_t contentPermissions) override {
     if ((contentType == DefinedAtom::typeStub) && (name.startswith(".text")))
-      return DefaultLayout<ELFT>::ORDER_TEXT;
+      return TargetLayout<ELFT>::ORDER_TEXT;
 
-    return DefaultLayout<ELFT>::getSectionOrder(name, contentType,
-                                                contentPermissions);
+    return TargetLayout<ELFT>::getSectionOrder(name, contentType,
+                                               contentPermissions);
   }
 
 protected:
@@ -130,7 +130,7 @@ public:
 
   MipsSymbolTable(const ELFLinkingContext &ctx)
       : SymbolTable<ELFT>(ctx, ".symtab",
-                          DefaultLayout<ELFT>::ORDER_SYMBOL_TABLE) {}
+                          TargetLayout<ELFT>::ORDER_SYMBOL_TABLE) {}
 
   void addDefinedAtom(Elf_Sym &sym, const DefinedAtom *da,
                       int64_t addr) override {
@@ -172,7 +172,7 @@ public:
   MipsDynamicSymbolTable(const ELFLinkingContext &ctx,
                          MipsTargetLayout<ELFT> &layout)
       : DynamicSymbolTable<ELFT>(ctx, layout, ".dynsym",
-                                 DefaultLayout<ELFT>::ORDER_DYNAMIC_SYMBOLS),
+                                 TargetLayout<ELFT>::ORDER_DYNAMIC_SYMBOLS),
         _targetLayout(layout) {}
 
   void sortSymbols() override {
index 68c258a..936d112 100644 (file)
@@ -9,7 +9,6 @@
 #ifndef LLD_READER_WRITER_ELF_OUTPUT_WRITER_H
 #define LLD_READER_WRITER_ELF_OUTPUT_WRITER_H
 
-#include "DefaultLayout.h"
 #include "ELFFile.h"
 #include "TargetLayout.h"
 #include "lld/Core/Instrumentation.h"
@@ -350,7 +349,7 @@ void OutputELFWriter<ELFT>::assignSectionsWithNoSegments() {
   _layout.assignFileOffsetsForMiscSections();
   for (auto sec : _layout.sections())
     if (auto section = dyn_cast<Section<ELFT>>(sec))
-      if (!DefaultLayout<ELFT>::hasOutputSegment(section))
+      if (!TargetLayout<ELFT>::hasOutputSegment(section))
         _shdrtab->updateSection(section);
 }
 
@@ -398,11 +397,11 @@ template <class ELFT> void OutputELFWriter<ELFT>::createDefaultSections() {
 
   _symtab = std::move(this->createSymbolTable());
   _strtab.reset(new (_alloc) StringTable<ELFT>(
-      _ctx, ".strtab", DefaultLayout<ELFT>::ORDER_STRING_TABLE));
+      _ctx, ".strtab", TargetLayout<ELFT>::ORDER_STRING_TABLE));
   _shstrtab.reset(new (_alloc) StringTable<ELFT>(
-      _ctx, ".shstrtab", DefaultLayout<ELFT>::ORDER_SECTION_STRINGS));
+      _ctx, ".shstrtab", TargetLayout<ELFT>::ORDER_SECTION_STRINGS));
   _shdrtab.reset(new (_alloc) SectionHeader<ELFT>(
-      _ctx, DefaultLayout<ELFT>::ORDER_SECTION_HEADERS));
+      _ctx, TargetLayout<ELFT>::ORDER_SECTION_HEADERS));
   _layout.addSection(_symtab.get());
   _layout.addSection(_strtab.get());
   _layout.addSection(_shstrtab.get());
@@ -416,8 +415,7 @@ template <class ELFT> void OutputELFWriter<ELFT>::createDefaultSections() {
     if (!section || section->outputSectionName() != ".eh_frame")
       continue;
     _ehFrameHeader.reset(new (_alloc) EHFrameHeader<ELFT>(
-        _ctx, ".eh_frame_hdr", _layout,
-        DefaultLayout<ELFT>::ORDER_EH_FRAMEHDR));
+        _ctx, ".eh_frame_hdr", _layout, TargetLayout<ELFT>::ORDER_EH_FRAMEHDR));
     _layout.addSection(_ehFrameHeader.get());
     break;
   }
@@ -425,10 +423,10 @@ template <class ELFT> void OutputELFWriter<ELFT>::createDefaultSections() {
   if (_ctx.isDynamic()) {
     _dynamicTable = std::move(createDynamicTable());
     _dynamicStringTable.reset(new (_alloc) StringTable<ELFT>(
-        _ctx, ".dynstr", DefaultLayout<ELFT>::ORDER_DYNAMIC_STRINGS, true));
+        _ctx, ".dynstr", TargetLayout<ELFT>::ORDER_DYNAMIC_STRINGS, true));
     _dynamicSymbolTable = std::move(createDynamicSymbolTable());
     _hashTable.reset(new (_alloc) HashSection<ELFT>(
-        _ctx, ".hash", DefaultLayout<ELFT>::ORDER_HASH));
+        _ctx, ".hash", TargetLayout<ELFT>::ORDER_HASH));
     // Set the hash table in the dynamic symbol table so that the entries in the
     // hash table can be created
     _dynamicSymbolTable->setHashTable(_hashTable.get());
@@ -453,7 +451,7 @@ template <class ELFT>
 unique_bump_ptr<SymbolTable<ELFT>>
     OutputELFWriter<ELFT>::createSymbolTable() {
   return unique_bump_ptr<SymbolTable<ELFT>>(new (_alloc) SymbolTable<ELFT>(
-      this->_ctx, ".symtab", DefaultLayout<ELFT>::ORDER_SYMBOL_TABLE));
+      this->_ctx, ".symtab", TargetLayout<ELFT>::ORDER_SYMBOL_TABLE));
 }
 
 /// \brief create dynamic table
@@ -461,7 +459,7 @@ template <class ELFT>
 unique_bump_ptr<DynamicTable<ELFT>>
     OutputELFWriter<ELFT>::createDynamicTable() {
   return unique_bump_ptr<DynamicTable<ELFT>>(new (_alloc) DynamicTable<ELFT>(
-      this->_ctx, _layout, ".dynamic", DefaultLayout<ELFT>::ORDER_DYNAMIC));
+      this->_ctx, _layout, ".dynamic", TargetLayout<ELFT>::ORDER_DYNAMIC));
 }
 
 /// \brief create dynamic symbol table
@@ -471,7 +469,7 @@ unique_bump_ptr<DynamicSymbolTable<ELFT>>
   return unique_bump_ptr<DynamicSymbolTable<ELFT>>(
       new (_alloc)
           DynamicSymbolTable<ELFT>(this->_ctx, _layout, ".dynsym",
-                                   DefaultLayout<ELFT>::ORDER_DYNAMIC_SYMBOLS));
+                                   TargetLayout<ELFT>::ORDER_DYNAMIC_SYMBOLS));
 }
 
 template <class ELFT>
index 4f8e8f1..462eacb 100644 (file)
@@ -29,7 +29,7 @@
 namespace lld {
 namespace elf {
 
-template <typename ELFT> class DefaultLayout;
+template <typename ELFT> class TargetLayout;
 
 /// \brief A segment can be divided into segment slices
 ///        depending on how the segments can be split
@@ -527,7 +527,7 @@ template <class ELFT> void Segment<ELFT>::assignVirtualAddress(uint64_t addr) {
       // segment. If we see a tbss section, don't add memory size to addr The
       // fileOffset is automatically taken care of since TBSS section does not
       // end up using file size
-      if ((*si)->order() != DefaultLayout<ELFT>::ORDER_TBSS)
+      if ((*si)->order() != TargetLayout<ELFT>::ORDER_TBSS)
         curSliceSize = (*si)->memSize();
     } else {
       uint64_t curAddr = curSliceAddress + curSliceSize;
@@ -610,7 +610,7 @@ template <class ELFT> void Segment<ELFT>::assignVirtualAddress(uint64_t addr) {
         // any segment. If we see a tbss section, don't add memory size to addr
         // The fileOffset is automatically taken care of since TBSS section does
         // not end up using file size.
-        if ((*si)->order() != DefaultLayout<ELFT>::ORDER_TBSS)
+        if ((*si)->order() != TargetLayout<ELFT>::ORDER_TBSS)
           curSliceSize = newAddr - curSliceAddress + (*si)->memSize();
         else
           curSliceSize = newAddr - curSliceAddress;
index 1bb0363..ee1f104 100644 (file)
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLD_READER_WRITER_ELF_TARGET_LAYOUT_H
-#define LLD_READER_WRITER_ELF_TARGET_LAYOUT_H
+#ifndef LLD_READER_WRITER_ELF_DEFAULT_LAYOUT_H
+#define LLD_READER_WRITER_ELF_DEFAULT_LAYOUT_H
 
-#include "DefaultLayout.h"
-#include "lld/Core/LLVM.h"
+#include "Atoms.h"
+#include "Chunk.h"
+#include "HeaderChunks.h"
+#include "Layout.h"
+#include "SectionChunks.h"
+#include "SegmentChunks.h"
+#include "lld/Core/Instrumentation.h"
+#include "lld/Core/STDExtras.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/Format.h"
+#include <map>
+#include <unordered_map>
 
 namespace lld {
 namespace elf {
-/// \brief The target can override certain functions in the DefaultLayout
-/// class so that the order, the name of the section and the segment type could
-/// be changed in the final layout
-template <class ELFT> class TargetLayout : public DefaultLayout<ELFT> {
+/// \brief The TargetLayout class is used by the Writer to arrange
+///        sections and segments in the order determined by the target ELF
+///        format. The writer creates a single instance of the TargetLayout
+///        class
+template<class ELFT>
+class TargetLayout : public Layout {
 public:
-  TargetLayout(ELFLinkingContext &ctx) : DefaultLayout<ELFT>(ctx) {}
+
+  // The order in which the sections appear in the output file
+  // If its determined, that the layout needs to change
+  // just changing the order of enumerations would essentially
+  // change the layout in the output file
+  // Change the enumerations so that Target can override and stick
+  // a section anywhere it wants to
+  enum DefaultSectionOrder {
+    ORDER_NOT_DEFINED = 0,
+    ORDER_INTERP = 10,
+    ORDER_RO_NOTE = 15,
+    ORDER_HASH = 30,
+    ORDER_DYNAMIC_SYMBOLS = 40,
+    ORDER_DYNAMIC_STRINGS = 50,
+    ORDER_DYNAMIC_RELOCS = 52,
+    ORDER_DYNAMIC_PLT_RELOCS = 54,
+    ORDER_INIT = 60,
+    ORDER_PLT = 70,
+    ORDER_TEXT = 80,
+    ORDER_FINI = 90,
+    ORDER_REL = 95,
+    ORDER_RODATA = 100,
+    ORDER_EH_FRAME = 110,
+    ORDER_EH_FRAMEHDR = 120,
+    ORDER_TDATA = 124,
+    ORDER_TBSS = 128,
+    ORDER_CTORS = 130,
+    ORDER_DTORS = 140,
+    ORDER_INIT_ARRAY = 150,
+    ORDER_FINI_ARRAY = 160,
+    ORDER_DYNAMIC = 170,
+    ORDER_GOT = 180,
+    ORDER_GOT_PLT = 190,
+    ORDER_DATA = 200,
+    ORDER_RW_NOTE = 205,
+    ORDER_BSS = 210,
+    ORDER_NOALLOC = 215,
+    ORDER_OTHER = 220,
+    ORDER_SECTION_STRINGS = 230,
+    ORDER_SYMBOL_TABLE = 240,
+    ORDER_STRING_TABLE = 250,
+    ORDER_SECTION_HEADERS = 260
+  };
+
+public:
+
+  // The Key used for creating Sections
+  // The sections are created using
+  // SectionName, contentPermissions
+  struct SectionKey {
+    SectionKey(StringRef name, DefinedAtom::ContentPermissions perm,
+               StringRef path)
+        : _name(name), _perm(perm), _path(path) {}
+
+    // Data members
+    StringRef _name;
+    DefinedAtom::ContentPermissions _perm;
+    StringRef _path;
+  };
+
+  struct SectionKeyHash {
+    int64_t operator()(const SectionKey &k) const {
+      return llvm::hash_combine(k._name, k._perm, k._path);
+    }
+  };
+
+  struct SectionKeyEq {
+    bool operator()(const SectionKey &lhs, const SectionKey &rhs) const {
+      return ((lhs._name == rhs._name) && (lhs._perm == rhs._perm) &&
+              (lhs._path == rhs._path));
+    }
+  };
+
+  typedef typename std::vector<Chunk<ELFT> *>::iterator ChunkIter;
+  typedef typename std::vector<Segment<ELFT> *>::iterator SegmentIter;
+
+  // The additional segments are used to figure out
+  // if there is a segment by that type already created
+  // For example : PT_TLS, we have two sections .tdata/.tbss
+  // that are part of PT_TLS, we need to create this additional
+  // segment only once
+  typedef std::pair<int64_t, int64_t> AdditionalSegmentKey;
+  // The segments are created using
+  // SegmentName, Segment flags
+  typedef std::pair<StringRef, int64_t> SegmentKey;
+
+  // HashKey for the Segment
+  class SegmentHashKey {
+  public:
+    int64_t operator() (const SegmentKey &k) const {
+      // k.first = SegmentName
+      // k.second = SegmentFlags
+      return llvm::hash_combine(k.first, k.second);
+    }
+  };
+
+  class AdditionalSegmentHashKey {
+  public:
+    int64_t operator()(const AdditionalSegmentKey &k) const {
+      // k.first = SegmentName
+      // k.second = SegmentFlags
+      return llvm::hash_combine(k.first, k.second);
+    }
+  };
+
+  // Output Sections contain the map of Sectionnames to a vector of sections,
+  // that have been merged to form a single section
+  typedef llvm::StringMap<OutputSection<ELFT> *> OutputSectionMapT;
+  typedef
+      typename std::vector<OutputSection<ELFT> *>::iterator OutputSectionIter;
+
+  typedef std::unordered_map<SectionKey, AtomSection<ELFT> *, SectionKeyHash,
+                             SectionKeyEq> SectionMapT;
+  typedef std::unordered_map<AdditionalSegmentKey, Segment<ELFT> *,
+                             AdditionalSegmentHashKey> AdditionalSegmentMapT;
+  typedef std::unordered_map<SegmentKey, Segment<ELFT> *, SegmentHashKey>
+  SegmentMapT;
+
+  typedef typename std::vector<lld::AtomLayout *>::iterator AbsoluteAtomIterT;
+
+  typedef llvm::DenseSet<const Atom *> AtomSetT;
+
+  TargetLayout(ELFLinkingContext &ctx)
+      : _ctx(ctx), _linkerScriptSema(ctx.linkerScriptSema()) {}
+
+  /// \brief Return the section order for a input section
+  SectionOrder getSectionOrder(StringRef name, int32_t contentType,
+                               int32_t contentPermissions) override;
+
+  /// \brief Return the name of the input section by decoding the input
+  /// sectionChoice.
+  virtual StringRef getInputSectionName(const DefinedAtom *da) const;
+
+  /// \brief Return the name of the output section from the input section.
+  virtual StringRef getOutputSectionName(StringRef archivePath,
+                                         StringRef memberPath,
+                                         StringRef inputSectionName) const;
+
+  /// \brief Gets or creates a section.
+  AtomSection<ELFT> *
+  getSection(StringRef name, int32_t contentType,
+             DefinedAtom::ContentPermissions contentPermissions,
+             const DefinedAtom *da);
+
+  /// \brief Gets the segment for a output section
+  virtual Layout::SegmentType getSegmentType(Section<ELFT> *section) const;
+
+  /// \brief Returns true/false depending on whether the section has a Output
+  //         segment or not
+  static bool hasOutputSegment(Section<ELFT> *section);
+
+  // Adds an atom to the section
+  ErrorOr<const lld::AtomLayout *> addAtom(const Atom *atom) override;
+
+  /// \brief Find an output Section given a section name.
+  OutputSection<ELFT> *findOutputSection(StringRef name) {
+    auto iter = _outputSectionMap.find(name);
+    if (iter == _outputSectionMap.end())
+      return nullptr;
+    return iter->second;
+  }
+
+  /// \brief find a absolute atom given a name
+  lld::AtomLayout *findAbsoluteAtom(StringRef name) {
+    auto iter = std::find_if(
+        _absoluteAtoms.begin(), _absoluteAtoms.end(),
+        [=](const AtomLayout *a) { return a->_atom->name() == name; });
+    if (iter == _absoluteAtoms.end())
+      return nullptr;
+    return *iter;
+  }
+
+  // Output sections with the same name into a OutputSection
+  void createOutputSections();
+
+  /// \brief Sort the sections by their order as defined by the layout,
+  /// preparing all sections to be assigned to a segment.
+  virtual void sortInputSections();
+
+  /// \brief Add extra chunks to a segment just before including the input
+  /// section given by <archivePath, memberPath, sectionName>. This
+  /// is used to add linker script expressions before each section.
+  virtual void addExtraChunksToSegment(Segment<ELFT> *segment,
+                                       StringRef archivePath,
+                                       StringRef memberPath,
+                                       StringRef sectionName);
+
+  void assignSectionsToSegments() override;
+
+  void assignVirtualAddress() override;
+
+  void assignFileOffsetsForMiscSections();
+
+  range<AbsoluteAtomIterT> absoluteAtoms() { return _absoluteAtoms; }
+
+  void addSection(Chunk<ELFT> *c) { _sections.push_back(c); }
+
+  void finalize() {
+    ScopedTask task(getDefaultDomain(), "Finalize layout");
+    for (auto &si : _sections)
+      si->finalize();
+  }
+
+  void doPreFlight() {
+    for (auto &si : _sections)
+      si->doPreFlight();
+  }
+
+  const AtomLayout *findAtomLayoutByName(StringRef name) const override {
+    for (auto sec : _sections)
+      if (auto section = dyn_cast<Section<ELFT>>(sec))
+        if (auto *al = section->findAtomLayoutByName(name))
+          return al;
+    return nullptr;
+  }
+
+  void setHeader(ELFHeader<ELFT> *elfHeader) { _elfHeader = elfHeader; }
+
+  void setProgramHeader(ProgramHeader<ELFT> *p) {
+    _programHeader = p;
+  }
+
+  range<OutputSectionIter> outputSections() { return _outputSections; }
+
+  range<ChunkIter> sections() { return _sections; }
+
+  range<SegmentIter> segments() { return _segments; }
+
+  ELFHeader<ELFT> *getHeader() { return _elfHeader; }
+
+  bool hasDynamicRelocationTable() const { return !!_dynamicRelocationTable; }
+
+  bool hasPLTRelocationTable() const { return !!_pltRelocationTable; }
+
+  /// \brief Get or create the dynamic relocation table. All relocations in this
+  /// table are processed at startup.
+  RelocationTable<ELFT> *getDynamicRelocationTable() {
+    if (!_dynamicRelocationTable) {
+      _dynamicRelocationTable = std::move(createRelocationTable(
+          _ctx.isRelaOutputFormat() ? ".rela.dyn" : ".rel.dyn",
+          ORDER_DYNAMIC_RELOCS));
+      addSection(_dynamicRelocationTable.get());
+    }
+    return _dynamicRelocationTable.get();
+  }
+
+  /// \brief Get or create the PLT relocation table. Referenced by DT_JMPREL.
+  RelocationTable<ELFT> *getPLTRelocationTable() {
+    if (!_pltRelocationTable) {
+      _pltRelocationTable = std::move(createRelocationTable(
+          _ctx.isRelaOutputFormat() ? ".rela.plt" : ".rel.plt",
+          ORDER_DYNAMIC_PLT_RELOCS));
+      addSection(_pltRelocationTable.get());
+    }
+    return _pltRelocationTable.get();
+  }
+
+  uint64_t getTLSSize() const {
+    for (const auto &phdr : *_programHeader)
+      if (phdr->p_type == llvm::ELF::PT_TLS)
+        return phdr->p_memsz;
+    return 0;
+  }
+
+  bool isReferencedByDefinedAtom(const Atom *a) const {
+    return _referencedDynAtoms.count(a);
+  }
+
+  bool isCopied(const SharedLibraryAtom *sla) const {
+    return _copiedDynSymNames.count(sla->name());
+  }
+
+protected:
+  /// \brief TargetLayouts may use these functions to reorder the input sections
+  /// in a order defined by their ABI.
+  virtual void finalizeOutputSectionLayout() {}
+
+  /// \brief Allocate a new section.
+  virtual AtomSection<ELFT> *createSection(
+      StringRef name, int32_t contentType,
+      DefinedAtom::ContentPermissions contentPermissions,
+      SectionOrder sectionOrder);
+
+  /// \brief Create a new relocation table.
+  virtual unique_bump_ptr<RelocationTable<ELFT>>
+  createRelocationTable(StringRef name, int32_t order) {
+    return unique_bump_ptr<RelocationTable<ELFT>>(
+        new (_allocator) RelocationTable<ELFT>(_ctx, name, order));
+  }
+
+protected:
+  llvm::BumpPtrAllocator _allocator;
+  SectionMapT _sectionMap;
+  OutputSectionMapT _outputSectionMap;
+  AdditionalSegmentMapT _additionalSegmentMap;
+  SegmentMapT _segmentMap;
+  std::vector<Chunk<ELFT> *> _sections;
+  std::vector<Segment<ELFT> *> _segments;
+  std::vector<OutputSection<ELFT> *> _outputSections;
+  ELFHeader<ELFT> *_elfHeader;
+  ProgramHeader<ELFT> *_programHeader;
+  unique_bump_ptr<RelocationTable<ELFT>> _dynamicRelocationTable;
+  unique_bump_ptr<RelocationTable<ELFT>> _pltRelocationTable;
+  std::vector<lld::AtomLayout *> _absoluteAtoms;
+  AtomSetT _referencedDynAtoms;
+  llvm::StringSet<> _copiedDynSymNames;
+  ELFLinkingContext &_ctx;
+  script::Sema &_linkerScriptSema;
 };
+
+template <class ELFT>
+Layout::SectionOrder
+TargetLayout<ELFT>::getSectionOrder(StringRef name, int32_t contentType,
+                                    int32_t contentPermissions) {
+  switch (contentType) {
+  case DefinedAtom::typeResolver:
+  case DefinedAtom::typeCode:
+    return llvm::StringSwitch<Layout::SectionOrder>(name)
+        .StartsWith(".eh_frame_hdr", ORDER_EH_FRAMEHDR)
+        .StartsWith(".eh_frame", ORDER_EH_FRAME)
+        .StartsWith(".init", ORDER_INIT)
+        .StartsWith(".fini", ORDER_FINI)
+        .StartsWith(".hash", ORDER_HASH)
+        .Default(ORDER_TEXT);
+
+  case DefinedAtom::typeConstant:
+    return ORDER_RODATA;
+
+  case DefinedAtom::typeData:
+  case DefinedAtom::typeDataFast:
+    return llvm::StringSwitch<Layout::SectionOrder>(name)
+        .StartsWith(".init_array", ORDER_INIT_ARRAY)
+        .StartsWith(".fini_array", ORDER_FINI_ARRAY)
+        .StartsWith(".dynamic", ORDER_DYNAMIC)
+        .StartsWith(".ctors", ORDER_CTORS)
+        .StartsWith(".dtors", ORDER_DTORS)
+        .Default(ORDER_DATA);
+
+  case DefinedAtom::typeZeroFill:
+  case DefinedAtom::typeZeroFillFast:
+    return ORDER_BSS;
+
+  case DefinedAtom::typeGOT:
+    return llvm::StringSwitch<Layout::SectionOrder>(name)
+        .StartsWith(".got.plt", ORDER_GOT_PLT)
+        .Default(ORDER_GOT);
+
+  case DefinedAtom::typeStub:
+    return ORDER_PLT;
+
+  case DefinedAtom::typeRONote:
+      return ORDER_RO_NOTE;
+
+  case DefinedAtom::typeRWNote:
+      return ORDER_RW_NOTE;
+
+  case DefinedAtom::typeNoAlloc:
+    return ORDER_NOALLOC;
+
+  case DefinedAtom::typeThreadData:
+    return ORDER_TDATA;
+  case DefinedAtom::typeThreadZeroFill:
+    return ORDER_TBSS;
+  default:
+    // If we get passed in a section push it to OTHER
+    if (contentPermissions == DefinedAtom::perm___)
+      return ORDER_OTHER;
+
+    return ORDER_NOT_DEFINED;
+  }
+}
+
+/// \brief This maps the input sections to the output section names
+template <class ELFT>
+StringRef TargetLayout<ELFT>::getInputSectionName(const DefinedAtom *da) const {
+  if (da->sectionChoice() == DefinedAtom::sectionBasedOnContent) {
+    switch (da->contentType()) {
+    case DefinedAtom::typeCode:
+      return ".text";
+    case DefinedAtom::typeData:
+      return ".data";
+    case DefinedAtom::typeConstant:
+      return ".rodata";
+    case DefinedAtom::typeZeroFill:
+      return ".bss";
+    case DefinedAtom::typeThreadData:
+      return ".tdata";
+    case DefinedAtom::typeThreadZeroFill:
+      return ".tbss";
+    default:
+      break;
+    }
+  }
+  return da->customSectionName();
+}
+
+/// \brief This maps the input sections to the output section names.
+template <class ELFT>
+StringRef
+TargetLayout<ELFT>::getOutputSectionName(StringRef archivePath,
+                                         StringRef memberPath,
+                                         StringRef inputSectionName) const {
+  StringRef outputSectionName;
+  if (_linkerScriptSema.hasLayoutCommands()) {
+    script::Sema::SectionKey key = {archivePath, memberPath, inputSectionName};
+    outputSectionName = _linkerScriptSema.getOutputSection(key);
+    if (!outputSectionName.empty())
+      return outputSectionName;
+  }
+  return llvm::StringSwitch<StringRef>(inputSectionName)
+      .StartsWith(".text", ".text")
+      .StartsWith(".ctors", ".ctors")
+      .StartsWith(".dtors", ".dtors")
+      .StartsWith(".rodata", ".rodata")
+      .StartsWith(".gcc_except_table", ".gcc_except_table")
+      .StartsWith(".data.rel.ro", ".data.rel.ro")
+      .StartsWith(".data.rel.local", ".data.rel.local")
+      .StartsWith(".data", ".data")
+      .StartsWith(".tdata", ".tdata")
+      .StartsWith(".tbss", ".tbss")
+      .StartsWith(".init_array", ".init_array")
+      .StartsWith(".fini_array", ".fini_array")
+      .Default(inputSectionName);
+}
+
+/// \brief Gets the segment for a output section
+template <class ELFT>
+Layout::SegmentType
+TargetLayout<ELFT>::getSegmentType(Section<ELFT> *section) const {
+  switch (section->order()) {
+  case ORDER_INTERP:
+    return llvm::ELF::PT_INTERP;
+
+  case ORDER_TEXT:
+  case ORDER_HASH:
+  case ORDER_DYNAMIC_SYMBOLS:
+  case ORDER_DYNAMIC_STRINGS:
+  case ORDER_DYNAMIC_RELOCS:
+  case ORDER_DYNAMIC_PLT_RELOCS:
+  case ORDER_REL:
+  case ORDER_INIT:
+  case ORDER_PLT:
+  case ORDER_FINI:
+  case ORDER_RODATA:
+  case ORDER_EH_FRAME:
+  case ORDER_CTORS:
+  case ORDER_DTORS:
+    return llvm::ELF::PT_LOAD;
+
+  case ORDER_RO_NOTE:
+  case ORDER_RW_NOTE:
+    return llvm::ELF::PT_NOTE;
+
+  case ORDER_DYNAMIC:
+    return llvm::ELF::PT_DYNAMIC;
+
+  case ORDER_EH_FRAMEHDR:
+    return llvm::ELF::PT_GNU_EH_FRAME;
+
+  case ORDER_GOT:
+  case ORDER_GOT_PLT:
+  case ORDER_DATA:
+  case ORDER_BSS:
+  case ORDER_INIT_ARRAY:
+  case ORDER_FINI_ARRAY:
+    return llvm::ELF::PT_LOAD;
+
+  case ORDER_TDATA:
+  case ORDER_TBSS:
+    return llvm::ELF::PT_TLS;
+
+  default:
+    return llvm::ELF::PT_NULL;
+  }
+}
+
+template <class ELFT>
+bool TargetLayout<ELFT>::hasOutputSegment(Section<ELFT> *section) {
+  switch (section->order()) {
+  case ORDER_INTERP:
+  case ORDER_HASH:
+  case ORDER_DYNAMIC_SYMBOLS:
+  case ORDER_DYNAMIC_STRINGS:
+  case ORDER_DYNAMIC_RELOCS:
+  case ORDER_DYNAMIC_PLT_RELOCS:
+  case ORDER_REL:
+  case ORDER_INIT:
+  case ORDER_PLT:
+  case ORDER_TEXT:
+  case ORDER_FINI:
+  case ORDER_RODATA:
+  case ORDER_EH_FRAME:
+  case ORDER_EH_FRAMEHDR:
+  case ORDER_TDATA:
+  case ORDER_TBSS:
+  case ORDER_RO_NOTE:
+  case ORDER_RW_NOTE:
+  case ORDER_DYNAMIC:
+  case ORDER_CTORS:
+  case ORDER_DTORS:
+  case ORDER_GOT:
+  case ORDER_GOT_PLT:
+  case ORDER_DATA:
+  case ORDER_INIT_ARRAY:
+  case ORDER_FINI_ARRAY:
+  case ORDER_BSS:
+  case ORDER_NOALLOC:
+    return true;
+  default:
+    return section->hasOutputSegment();
+  }
+}
+
+template <class ELFT>
+AtomSection<ELFT> *
+TargetLayout<ELFT>::createSection(StringRef sectionName, int32_t contentType,
+                                  DefinedAtom::ContentPermissions permissions,
+                                  SectionOrder sectionOrder) {
+  return new (_allocator) AtomSection<ELFT>(_ctx, sectionName, contentType,
+                                            permissions, sectionOrder);
+}
+
+template <class ELFT>
+AtomSection<ELFT> *
+TargetLayout<ELFT>::getSection(StringRef sectionName, int32_t contentType,
+                               DefinedAtom::ContentPermissions permissions,
+                               const DefinedAtom *da) {
+  const SectionKey sectionKey(sectionName, permissions, da->file().path());
+  SectionOrder sectionOrder = getSectionOrder(sectionName, contentType, permissions);
+  auto sec = _sectionMap.find(sectionKey);
+  if (sec != _sectionMap.end())
+    return sec->second;
+  AtomSection<ELFT> *newSec =
+      createSection(sectionName, contentType, permissions, sectionOrder);
+
+  newSec->setOutputSectionName(getOutputSectionName(
+      da->file().archivePath(), da->file().memberPath(), sectionName));
+  newSec->setOrder(sectionOrder);
+  newSec->setArchiveNameOrPath(da->file().archivePath());
+  newSec->setMemberNameOrPath(da->file().memberPath());
+  _sections.push_back(newSec);
+  _sectionMap.insert(std::make_pair(sectionKey, newSec));
+  return newSec;
+}
+
+template <class ELFT>
+ErrorOr<const lld::AtomLayout *> TargetLayout<ELFT>::addAtom(const Atom *atom) {
+  if (const DefinedAtom *definedAtom = dyn_cast<DefinedAtom>(atom)) {
+    // HACK: Ignore undefined atoms. We need to adjust the interface so that
+    // undefined atoms can still be included in the output symbol table for
+    // -noinhibit-exec.
+    if (definedAtom->contentType() == DefinedAtom::typeUnknown)
+      return make_error_code(llvm::errc::invalid_argument);
+    const DefinedAtom::ContentPermissions permissions =
+        definedAtom->permissions();
+    const DefinedAtom::ContentType contentType = definedAtom->contentType();
+
+    StringRef sectionName = getInputSectionName(definedAtom);
+    AtomSection<ELFT> *section =
+        getSection(sectionName, contentType, permissions, definedAtom);
+
+    // Add runtime relocations to the .rela section.
+    for (const auto &reloc : *definedAtom) {
+      bool isLocalReloc = true;
+      if (_ctx.isDynamicRelocation(*reloc)) {
+        getDynamicRelocationTable()->addRelocation(*definedAtom, *reloc);
+        isLocalReloc = false;
+      } else if (_ctx.isPLTRelocation(*reloc)) {
+        getPLTRelocationTable()->addRelocation(*definedAtom, *reloc);
+        isLocalReloc = false;
+      }
+
+      if (!reloc->target())
+        continue;
+
+      //Ignore undefined atoms that are not target of dynamic relocations
+      if (isa<UndefinedAtom>(reloc->target()) && isLocalReloc)
+        continue;
+
+      if (_ctx.isCopyRelocation(*reloc)) {
+        _copiedDynSymNames.insert(definedAtom->name());
+        continue;
+      }
+
+      _referencedDynAtoms.insert(reloc->target());
+    }
+    return section->appendAtom(atom);
+  }
+
+  const AbsoluteAtom *absoluteAtom = cast<AbsoluteAtom>(atom);
+  // Absolute atoms are not part of any section, they are global for the whole
+  // link
+  _absoluteAtoms.push_back(
+      new (_allocator) lld::AtomLayout(absoluteAtom, 0, absoluteAtom->value()));
+  return _absoluteAtoms.back();
+}
+
+/// Output sections with the same name into a OutputSection
+template <class ELFT> void TargetLayout<ELFT>::createOutputSections() {
+  OutputSection<ELFT> *outputSection;
+
+  for (auto &si : _sections) {
+    Section<ELFT> *section = dyn_cast<Section<ELFT>>(si);
+    if (!section)
+      continue;
+    const std::pair<StringRef, OutputSection<ELFT> *> currentOutputSection(
+        section->outputSectionName(), nullptr);
+    std::pair<typename OutputSectionMapT::iterator, bool> outputSectionInsert(
+        _outputSectionMap.insert(currentOutputSection));
+    if (!outputSectionInsert.second) {
+      outputSection = outputSectionInsert.first->second;
+    } else {
+      outputSection = new (_allocator.Allocate<OutputSection<ELFT>>())
+          OutputSection<ELFT>(section->outputSectionName());
+      _outputSections.push_back(outputSection);
+      outputSectionInsert.first->second = outputSection;
+    }
+    outputSection->appendSection(si);
+  }
+}
+
+template <class ELFT> void TargetLayout<ELFT>::assignSectionsToSegments() {
+  ScopedTask task(getDefaultDomain(), "assignSectionsToSegments");
+  ELFLinkingContext::OutputMagic outputMagic = _ctx.getOutputMagic();
+  // sort the sections by their order as defined by the layout
+  sortInputSections();
+
+  // Create output sections.
+  createOutputSections();
+
+  // Finalize output section layout.
+  finalizeOutputSectionLayout();
+
+  // Set the ordinal after sorting the sections
+  int ordinal = 1;
+  for (auto osi : _outputSections) {
+    osi->setOrdinal(ordinal);
+    for (auto ai : osi->sections()) {
+      ai->setOrdinal(ordinal);
+    }
+    ++ordinal;
+  }
+  for (auto osi : _outputSections) {
+    for (auto ai : osi->sections()) {
+      if (auto section = dyn_cast<Section<ELFT> >(ai)) {
+        if (!hasOutputSegment(section))
+          continue;
+
+        osi->setLoadableSection(section->isLoadableSection());
+
+        // Get the segment type for the section
+        int64_t segmentType = getSegmentType(section);
+
+        osi->setHasSegment();
+        section->setSegmentType(segmentType);
+        StringRef segmentName = section->segmentKindToStr();
+
+        int64_t lookupSectionFlag = osi->flags();
+        if ((!(lookupSectionFlag & llvm::ELF::SHF_WRITE)) &&
+            (_ctx.mergeRODataToTextSegment()))
+          lookupSectionFlag &= ~llvm::ELF::SHF_EXECINSTR;
+
+        // Merge string sections into Data segment itself
+        lookupSectionFlag &= ~(llvm::ELF::SHF_STRINGS | llvm::ELF::SHF_MERGE);
+
+        // Merge the TLS section into the DATA segment itself
+        lookupSectionFlag &= ~(llvm::ELF::SHF_TLS);
+
+        Segment<ELFT> *segment;
+        // We need a separate segment for sections that don't have
+        // the segment type to be PT_LOAD
+        if (segmentType != llvm::ELF::PT_LOAD) {
+          const AdditionalSegmentKey key(segmentType, lookupSectionFlag);
+          const std::pair<AdditionalSegmentKey, Segment<ELFT> *>
+          additionalSegment(key, nullptr);
+          std::pair<typename AdditionalSegmentMapT::iterator, bool>
+          additionalSegmentInsert(
+              _additionalSegmentMap.insert(additionalSegment));
+          if (!additionalSegmentInsert.second) {
+            segment = additionalSegmentInsert.first->second;
+          } else {
+            segment =
+                new (_allocator) Segment<ELFT>(_ctx, segmentName, segmentType);
+            additionalSegmentInsert.first->second = segment;
+            _segments.push_back(segment);
+          }
+          segment->append(section);
+        }
+        if (segmentType == llvm::ELF::PT_NULL)
+          continue;
+
+        // If the output magic is set to OutputMagic::NMAGIC or
+        // OutputMagic::OMAGIC, Place the data alongside text in one single
+        // segment
+        if (outputMagic == ELFLinkingContext::OutputMagic::NMAGIC ||
+            outputMagic == ELFLinkingContext::OutputMagic::OMAGIC)
+          lookupSectionFlag = llvm::ELF::SHF_EXECINSTR | llvm::ELF::SHF_ALLOC |
+                              llvm::ELF::SHF_WRITE;
+
+        // Use the flags of the merged Section for the segment
+        const SegmentKey key("PT_LOAD", lookupSectionFlag);
+        const std::pair<SegmentKey, Segment<ELFT> *> currentSegment(key,
+                                                                    nullptr);
+        std::pair<typename SegmentMapT::iterator, bool> segmentInsert(
+            _segmentMap.insert(currentSegment));
+        if (!segmentInsert.second) {
+          segment = segmentInsert.first->second;
+        } else {
+          segment = new (_allocator)
+              Segment<ELFT>(_ctx, "PT_LOAD", llvm::ELF::PT_LOAD);
+          segmentInsert.first->second = segment;
+          _segments.push_back(segment);
+        }
+        // Insert chunks with linker script expressions that occur at this
+        // point, just before appending a new input section
+        addExtraChunksToSegment(segment, section->archivePath(),
+                                section->memberPath(),
+                                section->inputSectionName());
+        segment->append(section);
+      }
+    }
+  }
+  if (_ctx.isDynamic() && !_ctx.isDynamicLibrary()) {
+    Segment<ELFT> *segment = new (_allocator) ProgramHeaderSegment<ELFT>(_ctx);
+    _segments.push_back(segment);
+    segment->append(_elfHeader);
+    segment->append(_programHeader);
+  }
+}
+
+template <class ELFT> void TargetLayout<ELFT>::assignVirtualAddress() {
+  if (_segments.empty())
+    return;
+
+  std::sort(_segments.begin(), _segments.end(), Segment<ELFT>::compareSegments);
+
+  uint64_t baseAddress = _ctx.getBaseAddress();
+
+  // HACK: This is a super dirty hack. The elf header and program header are
+  // not part of a section, but we need them to be loaded at the base address
+  // so that AT_PHDR is set correctly by the loader and so they are accessible
+  // at runtime. To do this we simply prepend them to the first loadable Segment
+  // and let the layout logic take care of it.
+  Segment<ELFT> *firstLoadSegment = nullptr;
+  for (auto si : _segments) {
+    if (si->segmentType() == llvm::ELF::PT_LOAD) {
+      firstLoadSegment = si;
+      si->firstSection()->setAlign(si->alignment());
+      break;
+    }
+  }
+  assert(firstLoadSegment != nullptr && "No loadable segment!");
+  firstLoadSegment->prepend(_programHeader);
+  firstLoadSegment->prepend(_elfHeader);
+  bool newSegmentHeaderAdded = true;
+  bool virtualAddressAssigned = false;
+  bool fileOffsetAssigned = false;
+  while (true) {
+    for (auto si : _segments) {
+      si->finalize();
+      // Don't add PT_NULL segments into the program header
+      if (si->segmentType() != llvm::ELF::PT_NULL)
+        newSegmentHeaderAdded = _programHeader->addSegment(si);
+    }
+    if (!newSegmentHeaderAdded && virtualAddressAssigned)
+      break;
+    uint64_t address = baseAddress;
+    // start assigning virtual addresses
+    for (auto &si : _segments) {
+      if ((si->segmentType() != llvm::ELF::PT_LOAD) &&
+          (si->segmentType() != llvm::ELF::PT_NULL))
+        continue;
+
+      if (si->segmentType() == llvm::ELF::PT_NULL) {
+        si->assignVirtualAddress(0 /*non loadable*/);
+      } else {
+        if (virtualAddressAssigned && (address != baseAddress) &&
+            (address == si->virtualAddr()))
+          break;
+        si->assignVirtualAddress(address);
+      }
+      address = si->virtualAddr() + si->memSize();
+    }
+    uint64_t baseFileOffset = 0;
+    uint64_t fileoffset = baseFileOffset;
+    for (auto &si : _segments) {
+      if ((si->segmentType() != llvm::ELF::PT_LOAD) &&
+          (si->segmentType() != llvm::ELF::PT_NULL))
+        continue;
+      if (fileOffsetAssigned && (fileoffset != baseFileOffset) &&
+          (fileoffset == si->fileOffset()))
+        break;
+      si->assignFileOffsets(fileoffset);
+      fileoffset = si->fileOffset() + si->fileSize();
+    }
+    virtualAddressAssigned = true;
+    fileOffsetAssigned = true;
+    _programHeader->resetProgramHeaders();
+  }
+  Section<ELFT> *section;
+  // Fix the offsets of all the atoms within a section
+  for (auto &si : _sections) {
+    section = dyn_cast<Section<ELFT>>(si);
+    if (section && TargetLayout<ELFT>::hasOutputSegment(section))
+      section->assignFileOffsets(section->fileOffset());
+  }
+  // Set the size of the merged Sections
+  for (auto osi : _outputSections) {
+    uint64_t sectionfileoffset = 0;
+    uint64_t startFileOffset = 0;
+    uint64_t sectionsize = 0;
+    bool isFirstSection = true;
+    for (auto si : osi->sections()) {
+      if (isFirstSection) {
+        startFileOffset = si->fileOffset();
+        isFirstSection = false;
+      }
+      sectionfileoffset = si->fileOffset();
+      sectionsize = si->fileSize();
+    }
+    sectionsize = (sectionfileoffset - startFileOffset) + sectionsize;
+    osi->setFileOffset(startFileOffset);
+    osi->setSize(sectionsize);
+  }
+  // Set the virtual addr of the merged Sections
+  for (auto osi : _outputSections) {
+    uint64_t sectionstartaddr = 0;
+    uint64_t startaddr = 0;
+    uint64_t sectionsize = 0;
+    bool isFirstSection = true;
+    for (auto si : osi->sections()) {
+      if (isFirstSection) {
+        startaddr = si->virtualAddr();
+        isFirstSection = false;
+      }
+      sectionstartaddr = si->virtualAddr();
+      sectionsize = si->memSize();
+    }
+    sectionsize = (sectionstartaddr - startaddr) + sectionsize;
+    osi->setMemSize(sectionsize);
+    osi->setAddr(startaddr);
+  }
+}
+
+template <class ELFT>
+void TargetLayout<ELFT>::assignFileOffsetsForMiscSections() {
+  uint64_t fileoffset = 0;
+  uint64_t size = 0;
+  for (auto si : _segments) {
+    // Don't calculate offsets from non loadable segments
+    if ((si->segmentType() != llvm::ELF::PT_LOAD) &&
+        (si->segmentType() != llvm::ELF::PT_NULL))
+      continue;
+    fileoffset = si->fileOffset();
+    size = si->fileSize();
+  }
+  fileoffset = fileoffset + size;
+  Section<ELFT> *section;
+  for (auto si : _sections) {
+    section = dyn_cast<Section<ELFT>>(si);
+    if (section && TargetLayout<ELFT>::hasOutputSegment(section))
+      continue;
+    fileoffset = llvm::RoundUpToAlignment(fileoffset, si->alignment());
+    si->setFileOffset(fileoffset);
+    si->setVirtualAddr(0);
+    fileoffset += si->fileSize();
+  }
+}
+
+template <class ELFT> void TargetLayout<ELFT>::sortInputSections() {
+  // First, sort according to default layout's order
+  std::stable_sort(
+      _sections.begin(), _sections.end(),
+      [](Chunk<ELFT> *A, Chunk<ELFT> *B) { return A->order() < B->order(); });
+
+  if (!_linkerScriptSema.hasLayoutCommands())
+    return;
+
+  // Sort the sections by their order as defined by the linker script
+  std::stable_sort(this->_sections.begin(), this->_sections.end(),
+                   [this](Chunk<ELFT> *A, Chunk<ELFT> *B) {
+                     auto *a = dyn_cast<Section<ELFT>>(A);
+                     auto *b = dyn_cast<Section<ELFT>>(B);
+
+                     if (a == nullptr)
+                       return false;
+                     if (b == nullptr)
+                       return true;
+
+                     return _linkerScriptSema.less(
+                         {a->archivePath(), a->memberPath(),
+                          a->inputSectionName()},
+                         {b->archivePath(), b->memberPath(),
+                          b->inputSectionName()});
+                   });
+  // Now try to arrange sections with no mapping rules to sections with
+  // similar content
+  auto p = this->_sections.begin();
+  // Find first section that has no assigned rule id
+  while (p != this->_sections.end()) {
+    auto *sect = dyn_cast<AtomSection<ELFT>>(*p);
+    if (!sect)
+      break;
+
+    if (!_linkerScriptSema.hasMapping({sect->archivePath(),
+                                       sect->memberPath(),
+                                       sect->inputSectionName()}))
+      break;
+
+    ++p;
+  }
+  // For all sections that have no assigned rule id, try to move them near a
+  // section with similar contents
+  if (p != this->_sections.begin()) {
+    for (; p != this->_sections.end(); ++p) {
+      auto q = p;
+      --q;
+      while (q != this->_sections.begin() &&
+             (*q)->getContentType() != (*p)->getContentType())
+        --q;
+      if ((*q)->getContentType() != (*p)->getContentType())
+        continue;
+      ++q;
+      for (auto i = p; i != q;) {
+        auto next = i--;
+        std::iter_swap(i, next);
+      }
+    }
+  }
+}
+
+template <class ELFT>
+void TargetLayout<ELFT>::addExtraChunksToSegment(Segment<ELFT> *segment,
+                                                 StringRef archivePath,
+                                                 StringRef memberPath,
+                                                 StringRef sectionName) {
+  if (!_linkerScriptSema.hasLayoutCommands())
+    return;
+
+  std::vector<const script::SymbolAssignment *> exprs =
+      _linkerScriptSema.getExprs({archivePath, memberPath, sectionName});
+  for (auto expr : exprs) {
+    auto expChunk =
+        new (this->_allocator) ExpressionChunk<ELFT>(this->_ctx, expr);
+    segment->append(expChunk);
+  }
+}
+
 } // end namespace elf
 } // end namespace lld