add_llvm_library(lldMipsELFTarget
+ MipsAbiInfoHandler.cpp
MipsCtorsOrderPass.cpp
MipsELFFile.cpp
- MipsELFFlagsMerger.cpp
MipsELFWriters.cpp
MipsLinkingContext.cpp
MipsRelocationHandler.cpp
-//===- lib/ReaderWriter/ELF/MipsELFFlagsMerger.cpp ------------------------===//
+//===- lib/ReaderWriter/ELF/MipsAbiInfoHandler.cpp ------------------------===//
//
// The LLVM Linker
//
//
//===----------------------------------------------------------------------===//
-#include "MipsELFFlagsMerger.h"
+#include "MipsAbiInfoHandler.h"
#include "lld/Core/Error.h"
+#include "lld/ReaderWriter/ELFLinkingContext.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/raw_ostream.h"
-using namespace lld;
-using namespace lld::elf;
using namespace llvm::ELF;
struct MipsISATreeEdge {
return false;
}
-MipsELFFlagsMerger::MipsELFFlagsMerger(bool is64Bits)
- : _is64Bit(is64Bits), _flags(0) {}
+namespace lld {
+namespace elf {
-uint32_t MipsELFFlagsMerger::getMergedELFFlags() const { return _flags; }
+template <class ELFT> uint32_t MipsAbiInfoHandler<ELFT>::getFlags() const {
+ return _flags;
+}
+
+template <class ELFT>
+const llvm::Optional<MipsReginfo> &
+MipsAbiInfoHandler<ELFT>::getRegistersMask() const {
+ return _regMask;
+}
-std::error_code MipsELFFlagsMerger::mergeFlags(uint32_t newFlags) {
+template <class ELFT>
+std::error_code MipsAbiInfoHandler<ELFT>::mergeFlags(uint32_t newFlags) {
// We support two ABI: O32 and N64. The last one does not have
// the corresponding ELF flag.
uint32_t inAbi = newFlags & EF_MIPS_ABI;
- uint32_t supportedAbi = _is64Bit ? 0 : uint32_t(EF_MIPS_ABI_O32);
+ uint32_t supportedAbi = ELFT::Is64Bits ? 0 : uint32_t(EF_MIPS_ABI_O32);
if (inAbi != supportedAbi)
return make_dynamic_error_code("Unsupported ABI");
return std::error_code();
}
+
+template <class ELFT>
+void MipsAbiInfoHandler<ELFT>::mergeRegistersMask(const MipsReginfo &info) {
+ std::lock_guard<std::mutex> lock(_mutex);
+ if (_regMask.hasValue())
+ _regMask->merge(info);
+ else
+ _regMask = info;
+}
+
+template class MipsAbiInfoHandler<ELF32LE>;
+template class MipsAbiInfoHandler<ELF64LE>;
+
+}
+}
--- /dev/null
+//===- lib/ReaderWriter/ELF/MipsAbiInfoHandler.h --------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLD_READER_WRITER_ELF_MIPS_MIPS_ABI_INFO_HANDLER_H
+#define LLD_READER_WRITER_ELF_MIPS_MIPS_ABI_INFO_HANDLER_H
+
+#include "MipsReginfo.h"
+#include "llvm/ADT/Optional.h"
+#include <mutex>
+#include <system_error>
+
+namespace lld {
+namespace elf {
+
+template <class ELFT> class MipsAbiInfoHandler {
+public:
+ MipsAbiInfoHandler() = default;
+
+ uint32_t getFlags() const;
+ const llvm::Optional<MipsReginfo> &getRegistersMask() const;
+
+ /// \brief Merge saved ELF header flags and the new set of flags.
+ std::error_code mergeFlags(uint32_t newFlags);
+
+ /// \brief Merge saved and new sets of registers usage masks.
+ void mergeRegistersMask(const MipsReginfo &info);
+
+private:
+ std::mutex _mutex;
+ uint32_t _flags = 0;
+ llvm::Optional<MipsReginfo> _regMask;
+};
+
+} // namespace elf
+} // namespace lld
+
+#endif
//===----------------------------------------------------------------------===//
#include "MipsELFFile.h"
+#include "MipsTargetHandler.h"
namespace lld {
namespace elf {
_dtpOff = sec->sh_addr + DTP_OFFSET;
}
- auto &ctx = static_cast<MipsLinkingContext &>(this->_ctx);
+ auto &handler =
+ static_cast<MipsTargetHandler<ELFT> &>(this->_ctx.getTargetHandler());
+ auto &abi = handler.getAbiInfoHandler();
ErrorOr<const Elf_Mips_RegInfo *> regInfoSec = findRegInfoSec();
if (auto ec = regInfoSec.getError())
return ec;
if (const Elf_Mips_RegInfo *regInfo = regInfoSec.get()) {
- ctx.mergeReginfoMask(*regInfo);
+ abi.mergeRegistersMask(*regInfo);
_gp0 = regInfo->ri_gp_value;
}
const Elf_Ehdr *hdr = this->_objFile->getHeader();
- if (std::error_code ec = ctx.mergeElfFlags(hdr->e_flags))
+ if (std::error_code ec = abi.mergeFlags(hdr->e_flags))
return ec;
return std::error_code();
+++ /dev/null
-//===- lib/ReaderWriter/ELF/MipsELFFlagsMerger.h --------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef LLD_READER_WRITER_ELF_MIPS_MIPS_ELF_FLAGS_MERGER_H
-#define LLD_READER_WRITER_ELF_MIPS_MIPS_ELF_FLAGS_MERGER_H
-
-#include <mutex>
-#include <system_error>
-
-namespace lld {
-namespace elf {
-
-class MipsELFFlagsMerger {
-public:
- MipsELFFlagsMerger(bool is64Bits);
-
- uint32_t getMergedELFFlags() const;
-
- /// \brief Merge saved ELF header flags and the new set of flags.
- std::error_code mergeFlags(uint32_t newFlags);
-
-private:
- const bool _is64Bit;
- std::mutex _mutex;
- uint32_t _flags;
-};
-
-} // namespace elf
-} // namespace lld
-
-#endif
template <class ELFT>
MipsELFWriter<ELFT>::MipsELFWriter(MipsLinkingContext &ctx,
- MipsTargetLayout<ELFT> &targetLayout)
- : _ctx(ctx), _targetLayout(targetLayout) {}
+ MipsTargetLayout<ELFT> &targetLayout,
+ const MipsAbiInfoHandler<ELFT> &abiInfo)
+ : _ctx(ctx), _targetLayout(targetLayout), _abiInfo(abiInfo) {}
template <class ELFT>
void MipsELFWriter<ELFT>::setELFHeader(ELFHeader<ELFT> &elfHeader) {
else
elfHeader.e_ident(llvm::ELF::EI_ABIVERSION, 0);
- elfHeader.e_flags(_ctx.getMergedELFFlags());
+ elfHeader.e_flags(_abiInfo.getFlags());
}
template <class ELFT>
}
template <class ELFT>
+unique_bump_ptr<Section<ELFT>>
+MipsELFWriter<ELFT>::createOptionsSection(llvm::BumpPtrAllocator &alloc) {
+ typedef unique_bump_ptr<Section<ELFT>> Ptr;
+ const auto ®Mask = _abiInfo.getRegistersMask();
+ if (!regMask.hasValue())
+ return Ptr();
+ return ELFT::Is64Bits
+ ? Ptr(new (alloc)
+ MipsOptionsSection<ELFT>(_ctx, _targetLayout, *regMask))
+ : Ptr(new (alloc)
+ MipsReginfoSection<ELFT>(_ctx, _targetLayout, *regMask));
+}
+
+template <class ELFT>
void MipsELFWriter<ELFT>::setAtomValue(StringRef name, uint64_t value) {
AtomLayout *atom = _targetLayout.findAbsoluteAtom(name);
assert(atom);
template <class ELFT>
MipsDynamicLibraryWriter<ELFT>::MipsDynamicLibraryWriter(
- MipsLinkingContext &ctx, MipsTargetLayout<ELFT> &layout)
- : DynamicLibraryWriter<ELFT>(ctx, layout), _writeHelper(ctx, layout),
- _targetLayout(layout) {}
+ MipsLinkingContext &ctx, MipsTargetLayout<ELFT> &layout,
+ const MipsAbiInfoHandler<ELFT> &abiInfo)
+ : DynamicLibraryWriter<ELFT>(ctx, layout),
+ _writeHelper(ctx, layout, abiInfo), _targetLayout(layout) {}
template <class ELFT>
void MipsDynamicLibraryWriter<ELFT>::createImplicitFiles(
template <class ELFT>
void MipsDynamicLibraryWriter<ELFT>::createDefaultSections() {
DynamicLibraryWriter<ELFT>::createDefaultSections();
- const auto &ctx = static_cast<const MipsLinkingContext &>(this->_ctx);
- const auto &mask = ctx.getMergedReginfoMask();
- if (!mask.hasValue())
- return;
- if (ELFT::Is64Bits)
- _reginfo = unique_bump_ptr<Section<ELFT>>(
- new (this->_alloc) MipsOptionsSection<ELFT>(ctx, _targetLayout, *mask));
- else
- _reginfo = unique_bump_ptr<Section<ELFT>>(
- new (this->_alloc) MipsReginfoSection<ELFT>(ctx, _targetLayout, *mask));
- this->_layout.addSection(_reginfo.get());
+ _reginfo = _writeHelper.createOptionsSection(this->_alloc);
+ if (_reginfo)
+ this->_layout.addSection(_reginfo.get());
}
template <class ELFT>
template class MipsDynamicLibraryWriter<ELF64LE>;
template <class ELFT>
-MipsExecutableWriter<ELFT>::MipsExecutableWriter(MipsLinkingContext &ctx,
- MipsTargetLayout<ELFT> &layout)
- : ExecutableWriter<ELFT>(ctx, layout), _writeHelper(ctx, layout),
+MipsExecutableWriter<ELFT>::MipsExecutableWriter(
+ MipsLinkingContext &ctx, MipsTargetLayout<ELFT> &layout,
+ const MipsAbiInfoHandler<ELFT> &abiInfo)
+ : ExecutableWriter<ELFT>(ctx, layout), _writeHelper(ctx, layout, abiInfo),
_targetLayout(layout) {}
template <class ELFT>
template <class ELFT> void MipsExecutableWriter<ELFT>::createDefaultSections() {
ExecutableWriter<ELFT>::createDefaultSections();
- const auto &ctx = static_cast<const MipsLinkingContext &>(this->_ctx);
- const auto &mask = ctx.getMergedReginfoMask();
- if (!mask.hasValue())
- return;
- if (ELFT::Is64Bits)
- _reginfo = unique_bump_ptr<Section<ELFT>>(
- new (this->_alloc) MipsOptionsSection<ELFT>(ctx, _targetLayout, *mask));
- else
- _reginfo = unique_bump_ptr<Section<ELFT>>(
- new (this->_alloc) MipsReginfoSection<ELFT>(ctx, _targetLayout, *mask));
- this->_layout.addSection(_reginfo.get());
+ _reginfo = _writeHelper.createOptionsSection(this->_alloc);
+ if (_reginfo)
+ this->_layout.addSection(_reginfo.get());
}
template <class ELFT>
#include "DynamicLibraryWriter.h"
#include "ExecutableWriter.h"
+#include "MipsAbiInfoHandler.h"
#include "MipsLinkingContext.h"
namespace lld {
template <typename ELFT> class MipsELFWriter {
public:
- MipsELFWriter(MipsLinkingContext &ctx, MipsTargetLayout<ELFT> &targetLayout);
+ MipsELFWriter(MipsLinkingContext &ctx, MipsTargetLayout<ELFT> &targetLayout,
+ const MipsAbiInfoHandler<ELFT> &abiInfo);
void setELFHeader(ELFHeader<ELFT> &elfHeader);
void finalizeMipsRuntimeAtomValues();
std::unique_ptr<RuntimeFile<ELFT>> createRuntimeFile();
+ unique_bump_ptr<Section<ELFT>>
+ createOptionsSection(llvm::BumpPtrAllocator &alloc);
private:
MipsLinkingContext &_ctx;
MipsTargetLayout<ELFT> &_targetLayout;
+ const MipsAbiInfoHandler<ELFT> &_abiInfo;
void setAtomValue(StringRef name, uint64_t value);
};
class MipsDynamicLibraryWriter : public DynamicLibraryWriter<ELFT> {
public:
MipsDynamicLibraryWriter(MipsLinkingContext &ctx,
- MipsTargetLayout<ELFT> &layout);
+ MipsTargetLayout<ELFT> &layout,
+ const MipsAbiInfoHandler<ELFT> &abiInfo);
protected:
// Add any runtime files and their atoms to the output
template <class ELFT>
class MipsExecutableWriter : public ExecutableWriter<ELFT> {
public:
- MipsExecutableWriter(MipsLinkingContext &ctx, MipsTargetLayout<ELFT> &layout);
+ MipsExecutableWriter(MipsLinkingContext &ctx, MipsTargetLayout<ELFT> &layout,
+ const MipsAbiInfoHandler<ELFT> &abiInfo);
protected:
void buildDynamicSymbolTable(const File &file) override;
}
MipsLinkingContext::MipsLinkingContext(llvm::Triple triple)
- : ELFLinkingContext(triple, createTarget(triple, *this)),
- _flagsMerger(triple.isArch64Bit()) {}
-
-std::error_code MipsLinkingContext::mergeElfFlags(uint64_t flags) {
- return _flagsMerger.mergeFlags(flags);
-}
-
-void MipsLinkingContext::mergeReginfoMask(const MipsReginfo &info) {
- std::lock_guard<std::mutex> lock(_maskMutex);
- if (_reginfoMask.hasValue())
- _reginfoMask->merge(info);
- else
- _reginfoMask = info;
-}
-
-uint32_t MipsLinkingContext::getMergedELFFlags() const {
- return _flagsMerger.getMergedELFFlags();
-}
-
-const llvm::Optional<MipsReginfo> &
-MipsLinkingContext::getMergedReginfoMask() const {
- return _reginfoMask;
-}
+ : ELFLinkingContext(triple, createTarget(triple, *this)) {}
uint64_t MipsLinkingContext::getBaseAddress() const {
if (_baseAddress == 0 && getOutputELFType() == llvm::ELF::ET_EXEC)
#ifndef LLD_READER_WRITER_ELF_MIPS_MIPS_LINKING_CONTEXT_H
#define LLD_READER_WRITER_ELF_MIPS_MIPS_LINKING_CONTEXT_H
-#include "MipsELFFlagsMerger.h"
-#include "MipsReginfo.h"
#include "lld/ReaderWriter/ELFLinkingContext.h"
-#include <mutex>
namespace lld {
namespace elf {
class MipsLinkingContext final : public ELFLinkingContext {
public:
- int getMachineType() const override { return llvm::ELF::EM_MIPS; }
MipsLinkingContext(llvm::Triple triple);
- std::error_code mergeElfFlags(uint64_t flags);
- void mergeReginfoMask(const MipsReginfo &info);
-
- uint32_t getMergedELFFlags() const;
- const llvm::Optional<MipsReginfo> &getMergedReginfoMask() const;
-
void registerRelocationNames(Registry &r) override;
-
- // ELFLinkingContext
+ int getMachineType() const override { return llvm::ELF::EM_MIPS; }
uint64_t getBaseAddress() const override;
StringRef entrySymbolName() const override;
StringRef getDefaultInterpreter() const override;
bool isCopyRelocation(const Reference &r) const override;
bool isPLTRelocation(const Reference &r) const override;
bool isRelativeReloc(const Reference &r) const override;
-
-private:
- MipsELFFlagsMerger _flagsMerger;
- std::mutex _maskMutex;
- llvm::Optional<MipsReginfo> _reginfoMask;
};
} // elf
#include "MipsELFFile.h"
#include "MipsLinkingContext.h"
#include "MipsRelocationPass.h"
+#include "MipsTargetHandler.h"
#include "llvm/ADT/DenseSet.h"
using namespace lld;
/// \brief Owner of all the Atoms created by this pass.
RelocationPassFile _file;
+ /// \brief Linked files contain MIPS R6 code.
+ bool _isMipsR6 = false;
+
+ /// \brief Linked files contain microMIPS code.
+ bool _isMicroMips = false;
+
/// \brief Map Atoms and addend to local GOT entries.
typedef std::pair<const Atom *, int64_t> LocalGotMapKeyT;
llvm::DenseMap<LocalGotMapKeyT, GOTAtom *> _gotLocalMap;
bool mightBeDynamic(const MipsELFDefinedAtom<ELFT> &atom,
Reference::KindValue refKind) const;
bool hasPLTEntry(const Atom *atom) const;
-
- bool isR6Target() const;
};
template <typename ELFT>
template <typename ELFT>
void RelocationPass<ELFT>::perform(std::unique_ptr<SimpleFile> &mf) {
+ auto &handler =
+ static_cast<MipsTargetHandler<ELFT> &>(this->_ctx.getTargetHandler());
+
+ uint32_t elfFlags = handler.getAbiInfoHandler().getFlags();
+ _isMicroMips = elfFlags & EF_MIPS_MICROMIPS;
+ _isMipsR6 = (elfFlags & EF_MIPS_ARCH) == EF_MIPS_ARCH_32R6 ||
+ (elfFlags & EF_MIPS_ARCH) == EF_MIPS_ARCH_64R6;
+
for (const auto &atom : mf->defined())
for (const auto &ref : *atom)
collectReferenceInfo(*cast<MipsELFDefinedAtom<ELFT>>(atom),
return _pltRegMap.count(atom) || _pltMicroMap.count(atom);
}
-template <typename ELFT> bool RelocationPass<ELFT>::isR6Target() const {
- switch (_ctx.getMergedELFFlags() & EF_MIPS_ARCH) {
- case EF_MIPS_ARCH_32R6:
- case EF_MIPS_ARCH_64R6:
- return true;
- default:
- return false;
- }
-}
-
template <typename ELFT>
bool RelocationPass<ELFT>::requirePLTEntry(const Atom *a) const {
if (!_hasStaticRelocations.count(a))
template <typename ELFT>
const PLTAtom *RelocationPass<ELFT>::getPLTEntry(const Atom *a) {
- bool hasMicroCode = _ctx.getMergedELFFlags() & EF_MIPS_MICROMIPS;
-
// If file contains microMIPS code try to reuse compressed PLT entry...
- if (hasMicroCode) {
+ if (_isMicroMips) {
auto microPLT = _pltMicroMap.find(a);
if (microPLT != _pltMicroMap.end())
return microPLT->second;
return regPLT->second;
// ... and finally prefer to create new compressed PLT entry.
- return hasMicroCode ? getPLTMicroEntry(a) : getPLTRegEntry(a);
+ return _isMicroMips ? getPLTMicroEntry(a) : getPLTRegEntry(a);
}
template <typename ELFT>
if (plt != _pltRegMap.end())
return plt->second;
- PLTAAtom *pa = isR6Target()
+ PLTAAtom *pa = _isMipsR6
? new (_file._alloc) PLTR6Atom(getGOTPLTEntry(a), _file)
: new (_file._alloc) PLTAAtom(getGOTPLTEntry(a), _file);
_pltRegMap[a] = pa;
std::unique_ptr<Writer> MipsTargetHandler<ELFT>::getWriter() {
switch (_ctx.getOutputELFType()) {
case llvm::ELF::ET_EXEC:
- return llvm::make_unique<MipsExecutableWriter<ELFT>>(_ctx, *_targetLayout);
+ return llvm::make_unique<MipsExecutableWriter<ELFT>>(_ctx, *_targetLayout,
+ _abiInfoHandler);
case llvm::ELF::ET_DYN:
- return llvm::make_unique<MipsDynamicLibraryWriter<ELFT>>(_ctx,
- *_targetLayout);
+ return llvm::make_unique<MipsDynamicLibraryWriter<ELFT>>(
+ _ctx, *_targetLayout, _abiInfoHandler);
case llvm::ELF::ET_REL:
llvm_unreachable("TODO: support -r mode");
default:
#ifndef LLD_READER_WRITER_ELF_MIPS_MIPS_TARGET_HANDLER_H
#define LLD_READER_WRITER_ELF_MIPS_MIPS_TARGET_HANDLER_H
+#include "MipsAbiInfoHandler.h"
#include "MipsLinkingContext.h"
#include "MipsTargetLayout.h"
#include "TargetHandler.h"
public:
MipsTargetHandler(MipsLinkingContext &ctx);
+ MipsAbiInfoHandler<ELFT> &getAbiInfoHandler() { return _abiInfoHandler; }
+
std::unique_ptr<Reader> getObjReader() override;
std::unique_ptr<Reader> getDSOReader() override;
const TargetRelocationHandler &getRelocationHandler() const override;
MipsLinkingContext &_ctx;
std::unique_ptr<MipsTargetLayout<ELFT>> _targetLayout;
std::unique_ptr<TargetRelocationHandler> _relocationHandler;
+ MipsAbiInfoHandler<ELFT> _abiInfoHandler;
};
template <class ELFT> class MipsSymbolTable : public SymbolTable<ELFT> {