diff options
Diffstat (limited to 'lld/lib/ReaderWriter/ELF')
-rw-r--r-- | lld/lib/ReaderWriter/ELF/Mips/MipsDynamicLibraryWriter.h | 16 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/ELF/Mips/MipsELFFile.h | 13 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/ELF/Mips/MipsExecutableWriter.h | 14 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp | 12 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h | 6 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/ELF/Mips/MipsReginfo.h | 29 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h | 47 |
7 files changed, 134 insertions, 3 deletions
diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsDynamicLibraryWriter.h b/lld/lib/ReaderWriter/ELF/Mips/MipsDynamicLibraryWriter.h index 034b57ca7c3..a72a467b808 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsDynamicLibraryWriter.h +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsDynamicLibraryWriter.h @@ -13,6 +13,7 @@ #include "MipsDynamicTable.h" #include "MipsELFWriters.h" #include "MipsLinkingContext.h" +#include "MipsSectionChunks.h" namespace lld { namespace elf { @@ -32,6 +33,7 @@ protected: bool createImplicitFiles(std::vector<std::unique_ptr<File>> &) override; void finalizeDefaultAtomValues() override; + void createDefaultSections() override; std::error_code setELFHeader() override { DynamicLibraryWriter<ELFT>::setELFHeader(); @@ -46,6 +48,7 @@ protected: private: MipsELFWriter<ELFT> _writeHelper; MipsTargetLayout<ELFT> &_targetLayout; + unique_bump_ptr<Section<ELFT>> _reginfo; }; template <class ELFT> @@ -70,6 +73,19 @@ void MipsDynamicLibraryWriter<ELFT>::finalizeDefaultAtomValues() { } template <class ELFT> +void MipsDynamicLibraryWriter<ELFT>::createDefaultSections() { + DynamicLibraryWriter<ELFT>::createDefaultSections(); + const auto &mask = + static_cast<const MipsLinkingContext &>(this->_ctx).getMergeReginfoMask(); + if (!ELFT::Is64Bits && mask.hasValue()) { + _reginfo = unique_bump_ptr<Section<ELFT>>( + new (this->_alloc) + MipsReginfoSection<ELFT>(this->_ctx, _targetLayout, *mask)); + this->_layout.addSection(_reginfo.get()); + } +} + +template <class ELFT> unique_bump_ptr<SymbolTable<ELFT>> MipsDynamicLibraryWriter<ELFT>::createSymbolTable() { return unique_bump_ptr<SymbolTable<ELFT>>( diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsELFFile.h b/lld/lib/ReaderWriter/ELF/Mips/MipsELFFile.h index 7376fb5f2cf..92d1165595e 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsELFFile.h +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsELFFile.h @@ -161,6 +161,8 @@ private: typedef llvm::object::Elf_RegInfo<ELFT> Elf_RegInfo; typedef llvm::object::Elf_Mips_Options<ELFT> Elf_Mips_Options; + auto &ctx = static_cast<MipsLinkingContext &>(this->_ctx); + if (const Elf_Shdr *sec = findSectionByType(SHT_MIPS_OPTIONS)) { auto contents = this->getSectionContents(sec); if (std::error_code ec = contents.getError()) @@ -172,9 +174,12 @@ private: return make_dynamic_error_code( StringRef("Invalid size of MIPS_OPTIONS section")); - const auto *opt = reinterpret_cast<const Elf_Mips_Options *>(raw.data()); + const auto *opt = + reinterpret_cast<const Elf_Mips_Options *>(raw.data()); if (opt->kind == ODK_REGINFO) { - _gp0 = reinterpret_cast<const Elf_RegInfo *>(opt + 1)->ri_gp_value; + const auto *regInfo = reinterpret_cast<const Elf_RegInfo *>(opt + 1); + ctx.mergeReginfoMask(*regInfo); + _gp0 = regInfo->ri_gp_value; break; } raw = raw.slice(opt->size); @@ -189,7 +194,9 @@ private: return make_dynamic_error_code( StringRef("Invalid size of MIPS_REGINFO section")); - _gp0 = reinterpret_cast<const Elf_RegInfo *>(raw.data())->ri_gp_value; + const auto *regInfo = reinterpret_cast<const Elf_RegInfo *>(raw.data()); + ctx.mergeReginfoMask(*regInfo); + _gp0 = regInfo->ri_gp_value; } return std::error_code(); } diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsExecutableWriter.h b/lld/lib/ReaderWriter/ELF/Mips/MipsExecutableWriter.h index 3927d69e6be..61e2eedc539 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsExecutableWriter.h +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsExecutableWriter.h @@ -31,6 +31,7 @@ protected: bool createImplicitFiles(std::vector<std::unique_ptr<File>> &) override; void finalizeDefaultAtomValues() override; + void createDefaultSections() override; std::error_code setELFHeader() override; unique_bump_ptr<SymbolTable<ELFT>> createSymbolTable() override; @@ -40,6 +41,7 @@ protected: private: MipsELFWriter<ELFT> _writeHelper; MipsTargetLayout<ELFT> &_targetLayout; + unique_bump_ptr<Section<ELFT>> _reginfo; }; template <class ELFT> @@ -122,6 +124,18 @@ void MipsExecutableWriter<ELFT>::finalizeDefaultAtomValues() { _writeHelper.finalizeMipsRuntimeAtomValues(); } +template <class ELFT> void MipsExecutableWriter<ELFT>::createDefaultSections() { + ExecutableWriter<ELFT>::createDefaultSections(); + const auto &mask = + static_cast<const MipsLinkingContext &>(this->_ctx).getMergeReginfoMask(); + if (!ELFT::Is64Bits && mask.hasValue()) { + _reginfo = unique_bump_ptr<Section<ELFT>>( + new (this->_alloc) + MipsReginfoSection<ELFT>(this->_ctx, _targetLayout, *mask)); + this->_layout.addSection(_reginfo.get()); + } +} + template <class ELFT> unique_bump_ptr<SymbolTable<ELFT>> MipsExecutableWriter<ELFT>::createSymbolTable() { diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp b/lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp index ea91fcfd6de..fcbd72471ee 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp @@ -47,10 +47,22 @@ std::error_code MipsLinkingContext::mergeHeaderFlags(uint8_t fileClass, return _flagsMerger.mergeHeaderFlags(fileClass, flags); } +void MipsLinkingContext::mergeReginfoMask(const MipsReginfo &info) { + if (_reginfoMask.hasValue()) + _reginfoMask->merge(info); + else + _reginfoMask = info; +} + uint32_t MipsLinkingContext::getMergedELFFlags() const { return _flagsMerger.getMergedELFFlags(); } +const llvm::Optional<MipsReginfo> & +MipsLinkingContext::getMergeReginfoMask() const { + return _reginfoMask; +} + uint64_t MipsLinkingContext::getBaseAddress() const { if (_baseAddress == 0 && getOutputELFType() == llvm::ELF::ET_EXEC) return getTriple().isArch64Bit() ? 0x120000000 : 0x400000; diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h b/lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h index f6679706866..d77ba25c965 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h @@ -10,6 +10,7 @@ #define LLD_READER_WRITER_ELF_MIPS_MIPS_LINKING_CONTEXT_H #include "MipsELFFlagsMerger.h" +#include "MipsReginfo.h" #include "lld/ReaderWriter/ELFLinkingContext.h" namespace lld { @@ -46,7 +47,11 @@ public: MipsLinkingContext(llvm::Triple triple); std::error_code mergeHeaderFlags(uint8_t fileClass, uint64_t flags) override; + void mergeReginfoMask(const MipsReginfo &info); + uint32_t getMergedELFFlags() const; + const llvm::Optional<MipsReginfo> &getMergeReginfoMask() const; + void registerRelocationNames(Registry &r) override; // ELFLinkingContext @@ -62,6 +67,7 @@ public: private: MipsELFFlagsMerger _flagsMerger; + llvm::Optional<MipsReginfo> _reginfoMask; }; } // elf diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsReginfo.h b/lld/lib/ReaderWriter/ELF/Mips/MipsReginfo.h index 01552a293de..83ccaa5e1a6 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsReginfo.h +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsReginfo.h @@ -47,4 +47,33 @@ template <class ELFT> struct Elf_Mips_Options { } // end namespace object. } // end namespace llvm. +namespace lld { +namespace elf { + +struct MipsReginfo { + uint32_t _gpRegMask = 0; + uint32_t _cpRegMask[4] = {0}; + + MipsReginfo() = default; + + template <class ElfReginfo> MipsReginfo(const ElfReginfo &elf) { + _gpRegMask = elf.ri_gprmask; + _cpRegMask[0] = elf.ri_cprmask[0]; + _cpRegMask[1] = elf.ri_cprmask[1]; + _cpRegMask[2] = elf.ri_cprmask[2]; + _cpRegMask[3] = elf.ri_cprmask[3]; + } + + void merge(const MipsReginfo &info) { + _gpRegMask |= info._gpRegMask; + _cpRegMask[0] |= info._cpRegMask[0]; + _cpRegMask[1] |= info._cpRegMask[1]; + _cpRegMask[2] |= info._cpRegMask[2]; + _cpRegMask[3] |= info._cpRegMask[3]; + } +}; + +} // end namespace elf +} // end namespace lld + #endif diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h b/lld/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h index 06142fd4c2a..67ec6f3d756 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h @@ -9,12 +9,59 @@ #ifndef LLD_READER_WRITER_ELF_MIPS_MIPS_SECTION_CHUNKS_H #define LLD_READER_WRITER_ELF_MIPS_MIPS_SECTION_CHUNKS_H +#include "MipsReginfo.h" + namespace lld { namespace elf { template <typename ELFT> class MipsTargetLayout; class MipsLinkingContext; +/// \brief Handle Mips .reginfo section +template <class ELFT> class MipsReginfoSection : public Section<ELFT> { +public: + MipsReginfoSection(const ELFLinkingContext &ctx, + MipsTargetLayout<ELFT> &targetLayout, + const MipsReginfo ®info) + : Section<ELFT>(ctx, ".reginfo", "MipsReginfo"), + _targetLayout(targetLayout) { + this->setOrder(MipsTargetLayout<ELFT>::ORDER_RO_NOTE); + this->_entSize = sizeof(Elf_RegInfo); + this->_fsize = sizeof(Elf_RegInfo); + this->_msize = sizeof(Elf_RegInfo); + this->_alignment = 4; + this->_type = SHT_MIPS_REGINFO; + this->_flags = SHF_ALLOC; + + memset(&_reginfo, 0, sizeof(_reginfo)); + _reginfo.ri_gprmask = reginfo._gpRegMask; + _reginfo.ri_cprmask[0] = reginfo._cpRegMask[0]; + _reginfo.ri_cprmask[1] = reginfo._cpRegMask[1]; + _reginfo.ri_cprmask[2] = reginfo._cpRegMask[2]; + _reginfo.ri_cprmask[3] = reginfo._cpRegMask[3]; + } + + void write(ELFWriter *writer, TargetLayout<ELFT> &layout, + llvm::FileOutputBuffer &buffer) override { + uint8_t *dest = buffer.getBufferStart() + this->fileOffset(); + std::memcpy(dest, &_reginfo, this->_fsize); + } + + void finalize() override { + const AtomLayout *gpAtom = _targetLayout.getGP(); + _reginfo.ri_gp_value = gpAtom ? gpAtom->_virtualAddr : 0;; + + if (this->_outputSection) + this->_outputSection->setType(this->_type); + } + +private: + typedef llvm::object::Elf_RegInfo<ELFT> Elf_RegInfo; + + Elf_RegInfo _reginfo; + MipsTargetLayout<ELFT> &_targetLayout; +}; + /// \brief Handle Mips GOT section template <class ELFT> class MipsGOTSection : public AtomSection<ELFT> { public: |