//===- lib/ReaderWriter/ELF/TargetLayout.cpp ------------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "TargetLayout.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Errc.h"

namespace lld {
namespace elf {

template <class ELFT>
typename TargetLayout<ELFT>::SectionOrder
TargetLayout<ELFT>::getSectionOrder(StringRef name, int32_t contentType,
                                    int32_t contentPermissions) {
  switch (contentType) {
  case DefinedAtom::typeResolver:
  case DefinedAtom::typeCode:
    return llvm::StringSwitch<typename TargetLayout<ELFT>::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<typename TargetLayout<ELFT>::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<typename TargetLayout<ELFT>::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>
typename TargetLayout<ELFT>::SegmentType
TargetLayout<ELFT>::getSegmentType(const 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 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) 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(section);
  }
}

template <class ELFT>
std::vector<typename TargetLayout<ELFT>::SegmentKey>
TargetLayout<ELFT>::getSegmentsForSection(const OutputSection<ELFT> *os,
                                          const Section<ELFT> *sec) const {
  std::vector<SegmentKey> segKeys;
  auto phdrs = _linkerScriptSema.getPHDRsForOutputSection(os->name());
  if (!phdrs.empty()) {
    if (phdrs.size() == 1 && phdrs[0]->isNone()) {
      segKeys.emplace_back("NONE", llvm::ELF::PT_NULL, 0, false);
      return segKeys;
    }

    for (auto phdr : phdrs) {
      segKeys.emplace_back(phdr->name(), phdr->type(), phdr->flags(), true);
    }
    return segKeys;
  }

  uint64_t flags = getLookupSectionFlags(os);
  int64_t segmentType = getSegmentType(sec);
  StringRef segmentName = sec->segmentKindToStr();

  // We need a separate segment for sections that don't have
  // the segment type to be PT_LOAD
  if (segmentType != llvm::ELF::PT_LOAD)
    segKeys.emplace_back(segmentName, segmentType, flags, false);

  if (segmentType == llvm::ELF::PT_NULL)
    return segKeys;

  // If the output magic is set to OutputMagic::NMAGIC or
  // OutputMagic::OMAGIC, Place the data alongside text in one single
  // segment
  ELFLinkingContext::OutputMagic outputMagic = _ctx.getOutputMagic();
  if (outputMagic == ELFLinkingContext::OutputMagic::NMAGIC ||
      outputMagic == ELFLinkingContext::OutputMagic::OMAGIC)
    flags =
        llvm::ELF::SHF_EXECINSTR | llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE;

  segKeys.emplace_back("LOAD", llvm::ELF::PT_LOAD, flags, false);
  return segKeys;
}

template <class ELFT>
uint64_t
TargetLayout<ELFT>::getLookupSectionFlags(const OutputSection<ELFT> *os) const {
  uint64_t flags = os->flags();
  if (!(flags & llvm::ELF::SHF_WRITE) && _ctx.mergeRODataToTextSegment())
    flags &= ~llvm::ELF::SHF_EXECINSTR;

  // Merge string sections into Data segment itself
  flags &= ~(llvm::ELF::SHF_STRINGS | llvm::ELF::SHF_MERGE);

  // Merge the TLS section into the DATA segment itself
  flags &= ~(llvm::ELF::SHF_TLS);
  return flags;
}

template <class ELFT> void TargetLayout<ELFT>::assignSectionsToSegments() {
  ScopedTask task(getDefaultDomain(), "assignSectionsToSegments");
  // 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 section : osi->sections()) {
      if (!hasOutputSegment(section))
        continue;

      osi->setLoadableSection(section->isLoadableSection());
      osi->setHasSegment();

      auto segKeys = getSegmentsForSection(osi, section);
      assert(!segKeys.empty() && "Must always be at least one segment");
      section->setSegmentType(segKeys[0]._type);

      for (auto key : segKeys) {
        // Try to find non-load (real) segment type if possible
        if (key._type != llvm::ELF::PT_LOAD)
          section->setSegmentType(key._type);

        const std::pair<SegmentKey, Segment<ELFT> *> currentSegment(key,
                                                                    nullptr);
        std::pair<typename SegmentMapT::iterator, bool> segmentInsert(
            _segmentMap.insert(currentSegment));
        Segment<ELFT> *segment;
        if (!segmentInsert.second) {
          segment = segmentInsert.first->second;
        } else {
          segment = new (_allocator) Segment<ELFT>(_ctx, key._name, key._type);
          if (key._segmentFlags)
            segment->setSegmentFlags(key._flags);
          segmentInsert.first->second = segment;
          _segments.push_back(segment);
        }
        if (key._type == llvm::ELF::PT_LOAD) {
          // 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);
      }
    }
  }

  // Default values if no linker script is available
  bool hasProgramSegment = _ctx.isDynamic() && !_ctx.isDynamicLibrary();
  bool hasElfHeader = true;
  bool hasProgramHeader = true;
  uint64_t segmentFlags = 0;

  // Check if linker script has PHDRS and program segment defined
  if (_linkerScriptSema.hasPHDRs()) {
    if (auto p = _linkerScriptSema.getProgramPHDR()) {
      hasProgramSegment = true;
      hasElfHeader = p->hasFileHdr();
      hasProgramHeader = p->hasPHDRs();
      segmentFlags = p->flags();
    } else {
      hasProgramSegment = false;
      hasElfHeader = false;
      hasProgramHeader = false;
    }
  }

  if (hasProgramSegment) {
    Segment<ELFT> *segment = new (_allocator) ProgramHeaderSegment<ELFT>(_ctx);
    _segments.push_back(segment);
    if (segmentFlags)
      segment->setSegmentFlags(segmentFlags);
    if (hasElfHeader)
      segment->append(_elfHeader);
    if (hasProgramHeader)
      segment->append(_programHeader);
  }
}

template <class ELFT> void TargetLayout<ELFT>::sortSegments() {
  std::sort(_segments.begin(), _segments.end(), Segment<ELFT>::compareSegments);
}

template <class ELFT> void TargetLayout<ELFT>::assignVirtualAddress() {
  if (_segments.empty())
    return;

  sortSegments();

  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>
const AtomLayout *
TargetLayout<ELFT>::findAtomLayoutByName(StringRef name) const {
  for (auto sec : _sections)
    if (auto section = dyn_cast<Section<ELFT>>(sec))
      if (auto *al = section->findAtomLayoutByName(name))
        return al;
  return nullptr;
}

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);
  }
}

template <class ELFT>
RelocationTable<ELFT> *TargetLayout<ELFT>::getDynamicRelocationTable() {
  if (!_dynamicRelocationTable) {
    _dynamicRelocationTable = createRelocationTable(
        _ctx.isRelaOutputFormat() ? ".rela.dyn" : ".rel.dyn",
        ORDER_DYNAMIC_RELOCS);
    addSection(_dynamicRelocationTable.get());
  }
  return _dynamicRelocationTable.get();
}

template <class ELFT>
RelocationTable<ELFT> *TargetLayout<ELFT>::getPLTRelocationTable() {
  if (!_pltRelocationTable) {
    _pltRelocationTable = createRelocationTable(
        _ctx.isRelaOutputFormat() ? ".rela.plt" : ".rel.plt",
        ORDER_DYNAMIC_PLT_RELOCS);
    addSection(_pltRelocationTable.get());
  }
  return _pltRelocationTable.get();
}

template <class ELFT> uint64_t TargetLayout<ELFT>::getTLSSize() const {
  for (const auto &phdr : *_programHeader)
    if (phdr->p_type == llvm::ELF::PT_TLS)
      return phdr->p_memsz;
  return 0;
}

template class TargetLayout<ELF32LE>;
template class TargetLayout<ELF32BE>;
template class TargetLayout<ELF64LE>;
template class TargetLayout<ELF64BE>;

} // end namespace elf
} // end namespace lld
