summaryrefslogtreecommitdiff
path: root/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp')
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp115
1 files changed, 115 insertions, 0 deletions
diff --git a/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp b/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp
new file mode 100644
index 0000000000000..7bffcbeb5c085
--- /dev/null
+++ b/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp
@@ -0,0 +1,115 @@
+//===- lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp -------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Atoms.h"
+#include "MipsCtorsOrderPass.h"
+#include "MipsLinkingContext.h"
+#include "MipsRelocationPass.h"
+#include "MipsTargetHandler.h"
+
+using namespace lld;
+using namespace lld::elf;
+
+std::unique_ptr<ELFLinkingContext>
+MipsLinkingContext::create(llvm::Triple triple) {
+ if (triple.getArch() == llvm::Triple::mipsel ||
+ triple.getArch() == llvm::Triple::mips64el)
+ return std::unique_ptr<ELFLinkingContext>(new MipsLinkingContext(triple));
+ return nullptr;
+}
+
+typedef std::unique_ptr<TargetHandlerBase> TargetHandlerBasePtr;
+
+static TargetHandlerBasePtr createTarget(llvm::Triple triple,
+ MipsLinkingContext &ctx) {
+ switch (triple.getArch()) {
+ case llvm::Triple::mipsel:
+ return TargetHandlerBasePtr(new MipsTargetHandler<Mips32ELType>(ctx));
+ case llvm::Triple::mips64el:
+ return TargetHandlerBasePtr(new MipsTargetHandler<Mips64ELType>(ctx));
+ default:
+ llvm_unreachable("Unhandled arch");
+ }
+}
+
+MipsLinkingContext::MipsLinkingContext(llvm::Triple triple)
+ : ELFLinkingContext(triple, createTarget(triple, *this)),
+ _flagsMerger(triple.isArch64Bit()) {}
+
+uint32_t MipsLinkingContext::getMergedELFFlags() const {
+ return _flagsMerger.getMergedELFFlags();
+}
+
+MipsELFFlagsMerger &MipsLinkingContext::getELFFlagsMerger() {
+ return _flagsMerger;
+}
+
+uint64_t MipsLinkingContext::getBaseAddress() const {
+ if (_baseAddress == 0 && getOutputELFType() == llvm::ELF::ET_EXEC)
+ return getTriple().isArch64Bit() ? 0x120000000 : 0x400000;
+ return _baseAddress;
+}
+
+StringRef MipsLinkingContext::entrySymbolName() const {
+ if (_outputELFType == elf::ET_EXEC && _entrySymbolName.empty())
+ return "__start";
+ return _entrySymbolName;
+}
+
+StringRef MipsLinkingContext::getDefaultInterpreter() const {
+ return getTriple().isArch64Bit() ? "/lib64/ld.so.1" : "/lib/ld.so.1";
+}
+
+void MipsLinkingContext::addPasses(PassManager &pm) {
+ auto pass = createMipsRelocationPass(*this);
+ if (pass)
+ pm.add(std::move(pass));
+ ELFLinkingContext::addPasses(pm);
+ pm.add(llvm::make_unique<elf::MipsCtorsOrderPass>());
+}
+
+bool MipsLinkingContext::isDynamicRelocation(const Reference &r) const {
+ if (r.kindNamespace() != Reference::KindNamespace::ELF)
+ return false;
+ assert(r.kindArch() == Reference::KindArch::Mips);
+ switch (r.kindValue()) {
+ case llvm::ELF::R_MIPS_COPY:
+ case llvm::ELF::R_MIPS_REL32:
+ case llvm::ELF::R_MIPS_TLS_DTPMOD32:
+ case llvm::ELF::R_MIPS_TLS_DTPREL32:
+ case llvm::ELF::R_MIPS_TLS_TPREL32:
+ case llvm::ELF::R_MIPS_TLS_DTPMOD64:
+ case llvm::ELF::R_MIPS_TLS_DTPREL64:
+ case llvm::ELF::R_MIPS_TLS_TPREL64:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool MipsLinkingContext::isCopyRelocation(const Reference &r) const {
+ if (r.kindNamespace() != Reference::KindNamespace::ELF)
+ return false;
+ assert(r.kindArch() == Reference::KindArch::Mips);
+ if (r.kindValue() == llvm::ELF::R_MIPS_COPY)
+ return true;
+ return false;
+}
+
+bool MipsLinkingContext::isPLTRelocation(const Reference &r) const {
+ if (r.kindNamespace() != Reference::KindNamespace::ELF)
+ return false;
+ assert(r.kindArch() == Reference::KindArch::Mips);
+ switch (r.kindValue()) {
+ case llvm::ELF::R_MIPS_JUMP_SLOT:
+ return true;
+ default:
+ return false;
+ }
+}