diff options
Diffstat (limited to 'lib/ReaderWriter/ELF/Mips/MipsTargetLayout.cpp')
| -rw-r--r-- | lib/ReaderWriter/ELF/Mips/MipsTargetLayout.cpp | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.cpp b/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.cpp new file mode 100644 index 0000000000000..710f8320a8b9c --- /dev/null +++ b/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.cpp @@ -0,0 +1,111 @@ +//===- 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 <class ELFT> +MipsTargetLayout<ELFT>::MipsTargetLayout(MipsLinkingContext &ctx, + MipsAbiInfoHandler<ELFT> &abi) + : TargetLayout<ELFT>(ctx), _abiInfo(abi), + _gotSection(new (this->_allocator) MipsGOTSection<ELFT>(ctx)), + _pltSection(new (this->_allocator) MipsPLTSection<ELFT>(ctx)) {} + +template <class ELFT> +AtomSection<ELFT> *MipsTargetLayout<ELFT>::createSection( + StringRef name, int32_t type, DefinedAtom::ContentPermissions permissions, + typename TargetLayout<ELFT>::SectionOrder order) { + if (type == DefinedAtom::typeGOT && name == ".got") + return _gotSection; + if (type == DefinedAtom::typeStub && name == ".plt") + return _pltSection; + return TargetLayout<ELFT>::createSection(name, type, permissions, order); +} + +template <class ELFT> +typename TargetLayout<ELFT>::SegmentType +MipsTargetLayout<ELFT>::getSegmentType(const Section<ELFT> *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<ELFT>::getSegmentType(section); + } +} + +template <class ELFT> uint64_t MipsTargetLayout<ELFT>::getGPAddr() { + std::call_once(_gpOnce, [this]() { + if (AtomLayout *a = this->findAbsoluteAtom("_gp")) + _gpAddr = a->_virtualAddr; + }); + return _gpAddr; +} + +template <class ELFT> +typename TargetLayout<ELFT>::SectionOrder +MipsTargetLayout<ELFT>::getSectionOrder(StringRef name, int32_t contentType, + int32_t contentPermissions) { + if ((contentType == DefinedAtom::typeStub) && (name.startswith(".text"))) + return TargetLayout<ELFT>::ORDER_TEXT; + + return TargetLayout<ELFT>::getSectionOrder(name, contentType, + contentPermissions); +} + +template <class ELFT> +unique_bump_ptr<RelocationTable<ELFT>> +MipsTargetLayout<ELFT>::createRelocationTable(StringRef name, int32_t order) { + return unique_bump_ptr<RelocationTable<ELFT>>(new ( + this->_allocator) MipsRelocationTable<ELFT>(this->_ctx, name, order)); +} + +template <class ELFT> +uint64_t MipsTargetLayout<ELFT>::getLookupSectionFlags( + const OutputSection<ELFT> *os) const { + uint64_t flags = TargetLayout<ELFT>::getLookupSectionFlags(os); + return flags & ~llvm::ELF::SHF_MIPS_NOSTRIP; +} + +template <class ELFT> void MipsTargetLayout<ELFT>::sortSegments() { + using namespace llvm::ELF; + TargetLayout<ELFT>::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<ELFT> *s) { + auto typ = s->segmentType(); + return typ == PT_MIPS_ABIFLAGS || typ == PT_MIPS_REGINFO; + }); + if (abiIt == this->_segments.end()) + return; + Segment<ELFT> *abiSeg = *abiIt; + this->_segments.erase(abiIt); + auto outIt = std::find_if(this->_segments.begin(), this->_segments.end(), + [](const Segment<ELFT> *s) { + auto typ = s->segmentType(); + return typ != PT_PHDR && typ != PT_INTERP; + }); + this->_segments.insert(outIt, abiSeg); +} + +template class MipsTargetLayout<ELF32BE>; +template class MipsTargetLayout<ELF32LE>; +template class MipsTargetLayout<ELF64BE>; +template class MipsTargetLayout<ELF64LE>; + +} // end namespace elf +} // end namespace lld |
