diff options
author | Simon Atanasyan <simon@atanasyan.com> | 2015-04-04 19:13:32 +0000 |
---|---|---|
committer | Simon Atanasyan <simon@atanasyan.com> | 2015-04-04 19:13:32 +0000 |
commit | c3899d22342fcaef6b02b22c136b3e06ea918f95 (patch) | |
tree | 437c4e8a992a6d03fc4d5cb402509917acb386cd /lld/lib/ReaderWriter | |
parent | 090132563b35651dc1ae67495b96bb781e68f9bd (diff) | |
download | bcm5719-llvm-c3899d22342fcaef6b02b22c136b3e06ea918f95.tar.gz bcm5719-llvm-c3899d22342fcaef6b02b22c136b3e06ea918f95.zip |
[Mips] Support writing .reginfo section into the linked file
In case of MIPS O32 ABI linker should merge registers usage masks stored
in the input .reginfo sections and save result into the output .reginfo
section.
The ABI states that the .reginfo section should be put into the separate
segment. This requirement is not implemented in this patch.
llvm-svn: 234103
Diffstat (limited to 'lld/lib/ReaderWriter')
-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: |