summaryrefslogtreecommitdiff
path: root/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ReaderWriter/ELF/Mips/MipsTargetLayout.cpp')
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsTargetLayout.cpp111
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