//===- lib/ReaderWriter/ELF/Mips/MipsTargetLayout.cpp ---------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "MipsLinkingContext.h" #include "MipsTargetLayout.h" namespace lld { namespace elf { template MipsTargetLayout::MipsTargetLayout(MipsLinkingContext &ctx, MipsAbiInfoHandler &abi) : TargetLayout(ctx), _abiInfo(abi), _gotSection(new (this->_allocator) MipsGOTSection(ctx)), _pltSection(new (this->_allocator) MipsPLTSection(ctx)) {} template AtomSection *MipsTargetLayout::createSection( StringRef name, int32_t type, DefinedAtom::ContentPermissions permissions, typename TargetLayout::SectionOrder order) { if (type == DefinedAtom::typeGOT && name == ".got") return _gotSection; if (type == DefinedAtom::typeStub && name == ".plt") return _pltSection; return TargetLayout::createSection(name, type, permissions, order); } template typename TargetLayout::SegmentType MipsTargetLayout::getSegmentType(const Section *section) const { switch (section->order()) { case ORDER_MIPS_REGINFO: return _abiInfo.hasMipsAbiSection() ? llvm::ELF::PT_LOAD : llvm::ELF::PT_MIPS_REGINFO; case ORDER_MIPS_OPTIONS: return llvm::ELF::PT_LOAD; case ORDER_MIPS_ABI_FLAGS: return llvm::ELF::PT_MIPS_ABIFLAGS; default: return TargetLayout::getSegmentType(section); } } template uint64_t MipsTargetLayout::getGPAddr() { std::call_once(_gpOnce, [this]() { if (AtomLayout *a = this->findAbsoluteAtom("_gp")) _gpAddr = a->_virtualAddr; }); return _gpAddr; } template typename TargetLayout::SectionOrder MipsTargetLayout::getSectionOrder(StringRef name, int32_t contentType, int32_t contentPermissions) { if ((contentType == DefinedAtom::typeStub) && (name.startswith(".text"))) return TargetLayout::ORDER_TEXT; return TargetLayout::getSectionOrder(name, contentType, contentPermissions); } template unique_bump_ptr> MipsTargetLayout::createRelocationTable(StringRef name, int32_t order) { return unique_bump_ptr>(new ( this->_allocator) MipsRelocationTable(this->_ctx, name, order)); } template uint64_t MipsTargetLayout::getLookupSectionFlags( const OutputSection *os) const { uint64_t flags = TargetLayout::getLookupSectionFlags(os); return flags & ~llvm::ELF::SHF_MIPS_NOSTRIP; } template void MipsTargetLayout::sortSegments() { using namespace llvm::ELF; TargetLayout::sortSegments(); // Move PT_MIPS_ABIFLAGS or PT_MIPS_REGINFO right after PT_INTERP. auto abiIt = std::find_if(this->_segments.begin(), this->_segments.end(), [](const Segment *s) { auto typ = s->segmentType(); return typ == PT_MIPS_ABIFLAGS || typ == PT_MIPS_REGINFO; }); if (abiIt == this->_segments.end()) return; Segment *abiSeg = *abiIt; this->_segments.erase(abiIt); auto outIt = std::find_if(this->_segments.begin(), this->_segments.end(), [](const Segment *s) { auto typ = s->segmentType(); return typ != PT_PHDR && typ != PT_INTERP; }); this->_segments.insert(outIt, abiSeg); } template class MipsTargetLayout; template class MipsTargetLayout; template class MipsTargetLayout; template class MipsTargetLayout; } // end namespace elf } // end namespace lld