diff options
Diffstat (limited to 'lld')
39 files changed, 1359 insertions, 674 deletions
diff --git a/lld/lib/ReaderWriter/ELF/Chunk.h b/lld/lib/ReaderWriter/ELF/Chunk.h index 271e50ba801..f8d3ffbc954 100644 --- a/lld/lib/ReaderWriter/ELF/Chunk.h +++ b/lld/lib/ReaderWriter/ELF/Chunk.h @@ -27,6 +27,8 @@ class ELFLinkingContext; namespace elf { class ELFWriter; +template <class ELFT> class TargetLayout; + /// \brief A chunk is a contiguous region of space template<class ELFT> class Chunk { @@ -73,7 +75,8 @@ public: // Whats the contentType of the chunk ? virtual int getContentType() const = 0; // Writer the chunk - virtual void write(ELFWriter *writer, llvm::FileOutputBuffer &buffer) = 0; + virtual void write(ELFWriter *writer, TargetLayout<ELFT> &layout, + llvm::FileOutputBuffer &buffer) = 0; // Finalize the chunk before assigning offsets/virtual addresses virtual void doPreFlight() = 0; // Finalize the chunk before writing diff --git a/lld/lib/ReaderWriter/ELF/DefaultTargetHandler.h b/lld/lib/ReaderWriter/ELF/DefaultTargetHandler.h index 0852bc854b2..7c305c0bd92 100644 --- a/lld/lib/ReaderWriter/ELF/DefaultTargetHandler.h +++ b/lld/lib/ReaderWriter/ELF/DefaultTargetHandler.h @@ -29,49 +29,10 @@ public: DefaultTargetHandler(ELFLinkingContext &context) : TargetHandler<ELFT>(context) {} - bool doesOverrideELFHeader() { return false; } - - void setELFHeader(ELFHeader<ELFT> *elfHeader) { - llvm_unreachable("Target should provide implementation for function "); - } - const TargetRelocationHandler<ELFT> &getRelocationHandler() const { llvm_unreachable("Target should provide implementation for function "); } - /// Create a set of Default target sections that a target might needj - void createDefaultSections() {} - - /// \brief Add a section to the current Layout - void addSection(Section<ELFT> *section) {} - - /// \brief add new symbol file - bool createImplicitFiles(std::vector<std::unique_ptr<File> > &) { - return true; - } - - /// \brief Finalize the symbol values - void finalizeSymbolValues() {} - - /// \brief allocate Commons, some architectures may move small common - /// symbols over to small data, this would also be used - void allocateCommons() {} - - /// \brief create dynamic table - LLD_UNIQUE_BUMP_PTR(DynamicTable<ELFT>) createDynamicTable() { - return LLD_UNIQUE_BUMP_PTR(DynamicTable<ELFT>)( - new (_alloc) DynamicTable<ELFT>( - this->_context, ".dynamic", DefaultLayout<ELFT>::ORDER_DYNAMIC)); - } - - /// \brief create dynamic symbol table - LLD_UNIQUE_BUMP_PTR(DynamicSymbolTable<ELFT>) createDynamicSymbolTable() { - return LLD_UNIQUE_BUMP_PTR(DynamicSymbolTable<ELFT>)( - new (_alloc) DynamicSymbolTable<ELFT>( - this->_context, ".dynsym", - DefaultLayout<ELFT>::ORDER_DYNAMIC_SYMBOLS)); - } - virtual std::unique_ptr<Reader> getObjReader(bool atomizeStrings) { return std::unique_ptr<Reader>(new ELFObjectReader(atomizeStrings)); } @@ -80,64 +41,9 @@ public: return std::unique_ptr<Reader>(new ELFDSOReader(useShlibUndefines)); } - virtual std::unique_ptr<Writer> getWriter(); - -protected: - llvm::BumpPtrAllocator _alloc; + virtual std::unique_ptr<Writer> getWriter() = 0; }; -template <class ELFT> -std::unique_ptr<Writer> DefaultTargetHandler<ELFT>::getWriter() { - switch (this->_context.getOutputELFType()) { - case llvm::ELF::ET_EXEC: - if (this->_context.is64Bits()) { - if (this->_context.isLittleEndian()) - return std::unique_ptr<Writer>( - new elf::ExecutableWriter<ELFType<support::little, 8, true>>( - this->_context)); - else - return std::unique_ptr<Writer>( - new elf::ExecutableWriter<ELFType<support::big, 8, true>>( - this->_context)); - } else { - if (this->_context.isLittleEndian()) - return std::unique_ptr<Writer>( - new elf::ExecutableWriter<ELFType<support::little, 4, false>>( - this->_context)); - else - return std::unique_ptr<Writer>( - new elf::ExecutableWriter<ELFType<support::big, 4, false>>( - this->_context)); - } - break; - case llvm::ELF::ET_DYN: - if (this->_context.is64Bits()) { - if (this->_context.isLittleEndian()) - return std::unique_ptr<Writer>( - new elf::DynamicLibraryWriter<ELFType<support::little, 8, true>>( - this->_context)); - else - return std::unique_ptr<Writer>( - new elf::DynamicLibraryWriter<ELFType<support::big, 8, true>>( - this->_context)); - } else { - if (this->_context.isLittleEndian()) - return std::unique_ptr<Writer>( - new elf::DynamicLibraryWriter<ELFType<support::little, 4, false>>( - this->_context)); - else - return std::unique_ptr<Writer>( - new elf::DynamicLibraryWriter<ELFType<support::big, 4, false>>( - this->_context)); - } - break; - case llvm::ELF::ET_REL: - llvm_unreachable("TODO: support -r mode"); - default: - llvm_unreachable("unsupported output type"); - } -} - } // end namespace elf } // end namespace lld #endif diff --git a/lld/lib/ReaderWriter/ELF/DynamicLibraryWriter.h b/lld/lib/ReaderWriter/ELF/DynamicLibraryWriter.h index 176a14f912f..84d6ac4a2d5 100644 --- a/lld/lib/ReaderWriter/ELF/DynamicLibraryWriter.h +++ b/lld/lib/ReaderWriter/ELF/DynamicLibraryWriter.h @@ -25,17 +25,18 @@ class DynamicLibraryWriter; template<class ELFT> class DynamicLibraryWriter : public OutputELFWriter<ELFT> { public: - DynamicLibraryWriter(const ELFLinkingContext &context) - : OutputELFWriter<ELFT>(context), + DynamicLibraryWriter(const ELFLinkingContext &context, + TargetLayout<ELFT> &layout) + : OutputELFWriter<ELFT>(context, layout), _runtimeFile(new CRuntimeFile<ELFT>(context)) {} -private: - void buildDynamicSymbolTable(const File &file); - void addDefaultAtoms(); +protected: + virtual void buildDynamicSymbolTable(const File &file); + virtual void addDefaultAtoms(); virtual bool createImplicitFiles(std::vector<std::unique_ptr<File> > &); - void finalizeDefaultAtomValues(); + virtual void finalizeDefaultAtomValues(); - llvm::BumpPtrAllocator _alloc; +protected: std::unique_ptr<CRuntimeFile<ELFT> > _runtimeFile; }; @@ -47,7 +48,7 @@ void DynamicLibraryWriter<ELFT>::buildDynamicSymbolTable(const File &file) { // Add all the defined symbols to the dynamic symbol table // we need hooks into the Atom to find out which atoms need // to be exported - for (auto sec : this->_layout->sections()) + for (auto sec : this->_layout.sections()) if (auto section = dyn_cast<AtomSection<ELFT>>(sec)) for (const auto &atom : section->atoms()) { const DefinedAtom *da = dyn_cast<const DefinedAtom>(atom->_atom); @@ -71,7 +72,7 @@ template <class ELFT> bool DynamicLibraryWriter<ELFT>::createImplicitFiles( std::vector<std::unique_ptr<File> > &result) { // Add the default atoms as defined by executables - addDefaultAtoms(); + DynamicLibraryWriter<ELFT>::addDefaultAtoms(); OutputELFWriter<ELFT>::createImplicitFiles(result); result.push_back(std::move(_runtimeFile)); return true; @@ -79,17 +80,15 @@ bool DynamicLibraryWriter<ELFT>::createImplicitFiles( template <class ELFT> void DynamicLibraryWriter<ELFT>::finalizeDefaultAtomValues() { - auto underScoreEndAtomIter = this->_layout->findAbsoluteAtom("_end"); + auto underScoreEndAtomIter = this->_layout.findAbsoluteAtom("_end"); - if (auto bssSection = this->_layout->findOutputSection(".bss")) { + if (auto bssSection = this->_layout.findOutputSection(".bss")) { (*underScoreEndAtomIter)->_virtualAddr = bssSection->virtualAddr() + bssSection->memSize(); - } else if (auto dataSection = this->_layout->findOutputSection(".data")) { + } else if (auto dataSection = this->_layout.findOutputSection(".data")) { (*underScoreEndAtomIter)->_virtualAddr = dataSection->virtualAddr() + dataSection->memSize(); } - - this->_targetHandler.finalizeSymbolValues(); } } // namespace elf diff --git a/lld/lib/ReaderWriter/ELF/ExecutableWriter.h b/lld/lib/ReaderWriter/ELF/ExecutableWriter.h index e4f84c8271a..af780b687e0 100644 --- a/lld/lib/ReaderWriter/ELF/ExecutableWriter.h +++ b/lld/lib/ReaderWriter/ELF/ExecutableWriter.h @@ -25,11 +25,11 @@ class ExecutableWriter; template<class ELFT> class ExecutableWriter : public OutputELFWriter<ELFT> { public: - ExecutableWriter(const ELFLinkingContext &context) - : OutputELFWriter<ELFT>(context), + ExecutableWriter(const ELFLinkingContext &context, TargetLayout<ELFT> &layout) + : OutputELFWriter<ELFT>(context, layout), _runtimeFile(new CRuntimeFile<ELFT>(context)) {} -private: +protected: virtual void addDefaultAtoms(); virtual bool createImplicitFiles(std::vector<std::unique_ptr<File> > &); virtual void finalizeDefaultAtomValues(); @@ -71,7 +71,7 @@ template <class ELFT> bool ExecutableWriter<ELFT>::createImplicitFiles( std::vector<std::unique_ptr<File> > &result) { // Add the default atoms as defined by executables - addDefaultAtoms(); + ExecutableWriter<ELFT>::addDefaultAtoms(); OutputELFWriter<ELFT>::createImplicitFiles(result); result.push_back(std::move(_runtimeFile)); return true; @@ -83,17 +83,17 @@ template <class ELFT> void ExecutableWriter<ELFT>::createDefaultSections() { _interpSection.reset(new (this->_alloc) InterpSection<ELFT>( this->_context, ".interp", DefaultLayout<ELFT>::ORDER_INTERP, this->_context.getInterpreter())); - this->_layout->addSection(_interpSection.get()); + this->_layout.addSection(_interpSection.get()); } } /// Finalize the value of all the absolute symbols that we /// created template <class ELFT> void ExecutableWriter<ELFT>::finalizeDefaultAtomValues() { - auto bssStartAtomIter = this->_layout->findAbsoluteAtom("__bss_start"); - auto bssEndAtomIter = this->_layout->findAbsoluteAtom("__bss_end"); - auto underScoreEndAtomIter = this->_layout->findAbsoluteAtom("_end"); - auto endAtomIter = this->_layout->findAbsoluteAtom("end"); + auto bssStartAtomIter = this->_layout.findAbsoluteAtom("__bss_start"); + auto bssEndAtomIter = this->_layout.findAbsoluteAtom("__bss_end"); + auto underScoreEndAtomIter = this->_layout.findAbsoluteAtom("_end"); + auto endAtomIter = this->_layout.findAbsoluteAtom("end"); auto startEnd = [&](StringRef sym, StringRef sec) -> void { // TODO: This looks like a good place to use Twine... @@ -102,9 +102,9 @@ template <class ELFT> void ExecutableWriter<ELFT>::finalizeDefaultAtomValues() { start += "_start"; end += sym; end += "_end"; - auto s = this->_layout->findAbsoluteAtom(start); - auto e = this->_layout->findAbsoluteAtom(end); - auto section = this->_layout->findOutputSection(sec); + auto s = this->_layout.findAbsoluteAtom(start); + auto e = this->_layout.findAbsoluteAtom(end); + auto section = this->_layout.findOutputSection(sec); if (section) { (*s)->_virtualAddr = section->virtualAddr(); (*e)->_virtualAddr = section->virtualAddr() + section->memSize(); @@ -122,13 +122,13 @@ template <class ELFT> void ExecutableWriter<ELFT>::finalizeDefaultAtomValues() { startEnd("rel_iplt", ".rel.plt"); startEnd("fini_array", ".fini_array"); - assert(!(bssStartAtomIter == this->_layout->absoluteAtoms().end() || - bssEndAtomIter == this->_layout->absoluteAtoms().end() || - underScoreEndAtomIter == this->_layout->absoluteAtoms().end() || - endAtomIter == this->_layout->absoluteAtoms().end()) && + assert(!(bssStartAtomIter == this->_layout.absoluteAtoms().end() || + bssEndAtomIter == this->_layout.absoluteAtoms().end() || + underScoreEndAtomIter == this->_layout.absoluteAtoms().end() || + endAtomIter == this->_layout.absoluteAtoms().end()) && "Unable to find the absolute atoms that have been added by lld"); - auto bssSection = this->_layout->findOutputSection(".bss"); + auto bssSection = this->_layout.findOutputSection(".bss"); // If we don't find a bss section, then don't set these values if (bssSection) { @@ -137,14 +137,11 @@ template <class ELFT> void ExecutableWriter<ELFT>::finalizeDefaultAtomValues() { bssSection->virtualAddr() + bssSection->memSize(); (*underScoreEndAtomIter)->_virtualAddr = (*bssEndAtomIter)->_virtualAddr; (*endAtomIter)->_virtualAddr = (*bssEndAtomIter)->_virtualAddr; - } else if (auto dataSection = this->_layout->findOutputSection(".data")) { + } else if (auto dataSection = this->_layout.findOutputSection(".data")) { (*underScoreEndAtomIter)->_virtualAddr = dataSection->virtualAddr() + dataSection->memSize(); (*endAtomIter)->_virtualAddr = (*underScoreEndAtomIter)->_virtualAddr; } - - // Give a chance for the target to finalize its atom values - this->_targetHandler.finalizeSymbolValues(); } } // namespace elf diff --git a/lld/lib/ReaderWriter/ELF/HeaderChunks.h b/lld/lib/ReaderWriter/ELF/HeaderChunks.h index d3f217b2eaf..cfcc6c6eccd 100644 --- a/lld/lib/ReaderWriter/ELF/HeaderChunks.h +++ b/lld/lib/ReaderWriter/ELF/HeaderChunks.h @@ -52,7 +52,8 @@ public: inline int getContentType() const { return Chunk<ELFT>::ContentType::Header; } - void write(ELFWriter *writer, llvm::FileOutputBuffer &buffer); + void write(ELFWriter *writer, TargetLayout<ELFT> &layout, + llvm::FileOutputBuffer &buffer); virtual void doPreFlight() {} @@ -78,7 +79,8 @@ ELFHeader<ELFT>::ELFHeader(const ELFLinkingContext &context) } template <class ELFT> -void ELFHeader<ELFT>::write(ELFWriter *writer, llvm::FileOutputBuffer &buffer) { +void ELFHeader<ELFT>::write(ELFWriter *writer, TargetLayout<ELFT> &layout, + llvm::FileOutputBuffer &buffer) { uint8_t *chunkBuffer = buffer.getBufferStart(); uint8_t *atomContent = chunkBuffer + this->fileOffset(); memcpy(atomContent, &_eh, fileSize()); @@ -132,7 +134,8 @@ public: return c->Kind() == Chunk<ELFT>::Kind::ProgramHeader; } - void write(ELFWriter *writer, llvm::FileOutputBuffer &buffer); + void write(ELFWriter *writer, TargetLayout<ELFT> &layout, + llvm::FileOutputBuffer &buffer); /// \brief find a program header entry in the list of program headers ReversePhIterT @@ -231,8 +234,8 @@ bool ProgramHeader<ELFT>::addSegment(Segment<ELFT> *segment) { } template <class ELFT> -void ProgramHeader<ELFT>::write(ELFWriter *writer, - llvm::FileOutputBuffer &buffer) { +void ProgramHeader<ELFT>::write(ELFWriter *writer, TargetLayout<ELFT> &layout, + llvm::FileOutputBuffer &buffer) { uint8_t *chunkBuffer = buffer.getBufferStart(); uint8_t *dest = chunkBuffer + this->fileOffset(); for (auto phi : _ph) { @@ -262,7 +265,8 @@ public: _stringSection = s; } - void write(ELFWriter *writer, llvm::FileOutputBuffer &buffer); + void write(ELFWriter *writer, TargetLayout<ELFT> &layout, + llvm::FileOutputBuffer &buffer); virtual void doPreFlight() {} @@ -336,15 +340,15 @@ SectionHeader<ELFT>::updateSection(Section<ELFT> *section) { } template <class ELFT> -void SectionHeader<ELFT>::write(ELFWriter *writer, - llvm::FileOutputBuffer &buffer) { +void SectionHeader<ELFT>::write(ELFWriter *writer, TargetLayout<ELFT> &layout, + llvm::FileOutputBuffer &buffer) { uint8_t *chunkBuffer = buffer.getBufferStart(); uint8_t *dest = chunkBuffer + this->fileOffset(); for (auto shi : _sectionInfo) { memcpy(dest, shi, sizeof(Elf_Shdr)); dest += sizeof(Elf_Shdr); } - _stringSection->write(writer, buffer); + _stringSection->write(writer, layout, buffer); } } // end namespace elf } // end namespace lld diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonDynamicLibraryWriter.h b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonDynamicLibraryWriter.h new file mode 100644 index 00000000000..06aae43ad69 --- /dev/null +++ b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonDynamicLibraryWriter.h @@ -0,0 +1,80 @@ +//===- lib/ReaderWriter/ELF/Hexagon/HexagonDynamicLibraryWriter.h +//-------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#ifndef HEXAGON_DYNAMIC_LIBRARY_WRITER_H +#define HEXAGON_DYNAMIC_LIBRARY_WRITER_H + +#include "HexagonExecutableAtoms.h" +#include "HexagonLinkingContext.h" +#include "DynamicLibraryWriter.h" + +namespace lld { +namespace elf { + +template <typename ELFT> class HexagonTargetLayout; + +template <class ELFT> +class HexagonDynamicLibraryWriter : public DynamicLibraryWriter<ELFT>, + public HexagonELFWriter<ELFT> { +public: + HexagonDynamicLibraryWriter(HexagonLinkingContext &context, + HexagonTargetLayout<ELFT> &layout); + +protected: + // Add any runtime files and their atoms to the output + virtual bool createImplicitFiles(std::vector<std::unique_ptr<File>> &); + + virtual void finalizeDefaultAtomValues(); + + virtual error_code setELFHeader() { + DynamicLibraryWriter<ELFT>::setELFHeader(); + HexagonELFWriter<ELFT>::setELFHeader(*this->_elfHeader); + return error_code::success(); + } + +private: + void addDefaultAtoms() { + _hexagonRuntimeFile->addAbsoluteAtom("_GLOBAL_OFFSET_TABLE_"); + _hexagonRuntimeFile->addAbsoluteAtom("_DYNAMIC"); + } + + HexagonLinkingContext &_hexagonLinkingContext; + HexagonTargetLayout<ELFT> &_hexagonTargetLayout; + std::unique_ptr<HexagonRuntimeFile<ELFT>> _hexagonRuntimeFile; +}; + +template <class ELFT> +HexagonDynamicLibraryWriter<ELFT>::HexagonDynamicLibraryWriter( + HexagonLinkingContext &context, HexagonTargetLayout<ELFT> &layout) + : DynamicLibraryWriter<ELFT>(context, layout), + HexagonELFWriter<ELFT>(context, layout), _hexagonLinkingContext(context), + _hexagonTargetLayout(layout), + _hexagonRuntimeFile(new HexagonRuntimeFile<ELFT>(context)) {} + +template <class ELFT> +bool HexagonDynamicLibraryWriter<ELFT>::createImplicitFiles( + std::vector<std::unique_ptr<File>> &result) { + DynamicLibraryWriter<ELFT>::createImplicitFiles(result); + // Add the default atoms as defined for hexagon + addDefaultAtoms(); + result.push_back(std::move(_hexagonRuntimeFile)); + return true; +} + +template <class ELFT> +void HexagonDynamicLibraryWriter<ELFT>::finalizeDefaultAtomValues() { + // Finalize the atom values that are part of the parent. + DynamicLibraryWriter<ELFT>::finalizeDefaultAtomValues(); + HexagonELFWriter<ELFT>::finalizeHexagonRuntimeAtomValues(); +} + +} // namespace elf +} // namespace lld + +#endif // HEXAGON_DYNAMIC_LIBRARY_WRITER_H diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonELFWriters.h b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonELFWriters.h new file mode 100644 index 00000000000..2e0fae3daf4 --- /dev/null +++ b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonELFWriters.h @@ -0,0 +1,61 @@ +//===- lib/ReaderWriter/ELF/Hexagon/HexagonELFWriters.h -------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef HEXAGON_ELF_WRITERS_H +#define HEXAGON_ELF_WRITERS_H + +#include "HexagonLinkingContext.h" +#include "OutputELFWriter.h" + +namespace lld { +namespace elf { + +template <class ELFT> class HexagonTargetLayout; + +template <typename ELFT> class HexagonELFWriter { +public: + HexagonELFWriter(HexagonLinkingContext &context, + HexagonTargetLayout<ELFT> &targetLayout) + : _hexagonLinkingContext(context), _hexagonTargetLayout(targetLayout) {} + +protected: + bool setELFHeader(ELFHeader<ELFT> &elfHeader) { + elfHeader.e_ident(llvm::ELF::EI_VERSION, 1); + elfHeader.e_ident(llvm::ELF::EI_OSABI, 0); + elfHeader.e_version(1); + elfHeader.e_flags(0x3); + return true; + } + + void finalizeHexagonRuntimeAtomValues() { + if (_hexagonLinkingContext.isDynamic()) { + auto gotAtomIter = + _hexagonTargetLayout.findAbsoluteAtom("_GLOBAL_OFFSET_TABLE_"); + auto gotpltSection = _hexagonTargetLayout.findOutputSection(".got.plt"); + if (gotpltSection) + (*gotAtomIter)->_virtualAddr = gotpltSection->virtualAddr(); + else + (*gotAtomIter)->_virtualAddr = 0; + auto dynamicAtomIter = _hexagonTargetLayout.findAbsoluteAtom("_DYNAMIC"); + auto dynamicSection = _hexagonTargetLayout.findOutputSection(".dynamic"); + if (dynamicSection) + (*dynamicAtomIter)->_virtualAddr = dynamicSection->virtualAddr(); + else + (*dynamicAtomIter)->_virtualAddr = 0; + } + } + +private: + HexagonLinkingContext &_hexagonLinkingContext LLVM_ATTRIBUTE_UNUSED; + HexagonTargetLayout<ELFT> &_hexagonTargetLayout; +}; + +} // elf +} // lld +#endif // HEXAGON_ELF_WRITERS_H diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonExecutableWriter.h b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonExecutableWriter.h new file mode 100644 index 00000000000..291b2d6fb8a --- /dev/null +++ b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonExecutableWriter.h @@ -0,0 +1,86 @@ +//===- lib/ReaderWriter/ELF/Hexagon/HexagonExecutableWriter.h -------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#ifndef HEXAGON_EXECUTABLE_WRITER_H +#define HEXAGON_EXECUTABLE_WRITER_H + +#include "HexagonExecutableAtoms.h" +#include "HexagonLinkingContext.h" +#include "HexagonELFWriters.h" +#include "ExecutableWriter.h" + +namespace lld { +namespace elf { + +template <typename ELFT> class HexagonTargetLayout; + +template <class ELFT> +class HexagonExecutableWriter : public ExecutableWriter<ELFT>, + public HexagonELFWriter<ELFT> { +public: + HexagonExecutableWriter(HexagonLinkingContext &context, + HexagonTargetLayout<ELFT> &layout); + +protected: + // Add any runtime files and their atoms to the output + virtual bool createImplicitFiles(std::vector<std::unique_ptr<File>> &); + + virtual void finalizeDefaultAtomValues(); + + virtual error_code setELFHeader() { + ExecutableWriter<ELFT>::setELFHeader(); + HexagonELFWriter<ELFT>::setELFHeader(*this->_elfHeader); + return error_code::success(); + } + +private: + void addDefaultAtoms() { + _hexagonRuntimeFile->addAbsoluteAtom("_SDA_BASE_"); + if (this->_context.isDynamic()) { + _hexagonRuntimeFile->addAbsoluteAtom("_GLOBAL_OFFSET_TABLE_"); + _hexagonRuntimeFile->addAbsoluteAtom("_DYNAMIC"); + } + } + + HexagonLinkingContext &_hexagonLinkingContext; + HexagonTargetLayout<ELFT> &_hexagonTargetLayout; + std::unique_ptr<HexagonRuntimeFile<ELFT>> _hexagonRuntimeFile; +}; + +template <class ELFT> +HexagonExecutableWriter<ELFT>::HexagonExecutableWriter( + HexagonLinkingContext &context, HexagonTargetLayout<ELFT> &layout) + : ExecutableWriter<ELFT>(context, layout), + HexagonELFWriter<ELFT>(context, layout), _hexagonLinkingContext(context), + _hexagonTargetLayout(layout), + _hexagonRuntimeFile(new HexagonRuntimeFile<ELFT>(context)) {} + +template <class ELFT> +bool HexagonExecutableWriter<ELFT>::createImplicitFiles( + std::vector<std::unique_ptr<File>> &result) { + ExecutableWriter<ELFT>::createImplicitFiles(result); + // Add the default atoms as defined for hexagon + addDefaultAtoms(); + result.push_back(std::move(_hexagonRuntimeFile)); + return true; +} + +template <class ELFT> +void HexagonExecutableWriter<ELFT>::finalizeDefaultAtomValues() { + // Finalize the atom values that are part of the parent. + ExecutableWriter<ELFT>::finalizeDefaultAtomValues(); + auto sdabaseAtomIter = _hexagonTargetLayout.findAbsoluteAtom("_SDA_BASE_"); + (*sdabaseAtomIter)->_virtualAddr = + _hexagonTargetLayout.getSDataSection()->virtualAddr(); + HexagonELFWriter<ELFT>::finalizeHexagonRuntimeAtomValues(); +} + +} // namespace elf +} // namespace lld + +#endif // HEXAGON_EXECUTABLE_WRITER_H diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.h b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.h index 6eb619675d9..db863069746 100644 --- a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.h +++ b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.h @@ -18,6 +18,8 @@ namespace lld { namespace elf { +typedef llvm::object::ELFType<llvm::support::little, 2, false> HexagonELFType; + class HexagonLinkingContext LLVM_FINAL : public ELFLinkingContext { public: HexagonLinkingContext(llvm::Triple triple); diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp index 4e6d1ead4f2..22f10f7f74b 100644 --- a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp +++ b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp @@ -264,19 +264,19 @@ error_code HexagonTargetRelocationHandler::applyRelocation( break; case R_HEX_GPREL16_0: relocHexGPRELN(location, relocVAddress, targetVAddress, ref.addend(), - _targetLayout.getSDataSection()->virtualAddr(), 0); + _hexagonTargetLayout.getSDataSection()->virtualAddr(), 0); break; case R_HEX_GPREL16_1: relocHexGPRELN(location, relocVAddress, targetVAddress, ref.addend(), - _targetLayout.getSDataSection()->virtualAddr(), 1); + _hexagonTargetLayout.getSDataSection()->virtualAddr(), 1); break; case R_HEX_GPREL16_2: relocHexGPRELN(location, relocVAddress, targetVAddress, ref.addend(), - _targetLayout.getSDataSection()->virtualAddr(), 2); + _hexagonTargetLayout.getSDataSection()->virtualAddr(), 2); break; case R_HEX_GPREL16_3: relocHexGPRELN(location, relocVAddress, targetVAddress, ref.addend(), - _targetLayout.getSDataSection()->virtualAddr(), 3); + _hexagonTargetLayout.getSDataSection()->virtualAddr(), 3); break; case R_HEX_16_X: case R_HEX_12_X: @@ -296,45 +296,52 @@ error_code HexagonTargetRelocationHandler::applyRelocation( break; case R_HEX_GOTREL_32: relocHexGOTREL_32(location, relocVAddress, targetVAddress, ref.addend(), - _targetHandler.getGOTSymAddr()); + _hexagonTargetLayout.getGOTSymAddr()); break; case R_HEX_GOTREL_LO16: relocHexGOTREL_HILO16(location, relocVAddress, targetVAddress, ref.addend(), - _targetHandler.getGOTSymAddr()); + _hexagonTargetLayout.getGOTSymAddr()); break; case R_HEX_GOTREL_HI16: relocHexGOTREL_HILO16(location, relocVAddress, targetVAddress, ref.addend(), - _targetHandler.getGOTSymAddr(), 16); + _hexagonTargetLayout.getGOTSymAddr(), 16); break; case R_HEX_GOT_LO16: - relocHexGOTLO16(location, targetVAddress, _targetHandler.getGOTSymAddr()); + relocHexGOTLO16(location, targetVAddress, + _hexagonTargetLayout.getGOTSymAddr()); break; case R_HEX_GOT_HI16: - relocHexGOTHI16(location, targetVAddress, _targetHandler.getGOTSymAddr()); + relocHexGOTHI16(location, targetVAddress, + _hexagonTargetLayout.getGOTSymAddr()); break; case R_HEX_GOT_32: - relocHexGOT32(location, targetVAddress, _targetHandler.getGOTSymAddr()); + relocHexGOT32(location, targetVAddress, + _hexagonTargetLayout.getGOTSymAddr()); break; case R_HEX_GOT_16: - relocHexGOT16(location, targetVAddress, _targetHandler.getGOTSymAddr()); + relocHexGOT16(location, targetVAddress, + _hexagonTargetLayout.getGOTSymAddr()); break; case R_HEX_GOT_32_6_X: - relocHexGOT32_6_X(location, targetVAddress, _targetHandler.getGOTSymAddr()); + relocHexGOT32_6_X(location, targetVAddress, + _hexagonTargetLayout.getGOTSymAddr()); break; case R_HEX_GOT_16_X: - relocHexGOT16_X(location, targetVAddress, _targetHandler.getGOTSymAddr()); + relocHexGOT16_X(location, targetVAddress, + _hexagonTargetLayout.getGOTSymAddr()); break; case R_HEX_GOT_11_X: - relocHexGOT11_X(location, targetVAddress, _targetHandler.getGOTSymAddr()); + relocHexGOT11_X(location, targetVAddress, + _hexagonTargetLayout.getGOTSymAddr()); break; case R_HEX_GOTREL_32_6_X: relocHexGOTRELSigned(location, relocVAddress, targetVAddress, ref.addend(), - _targetHandler.getGOTSymAddr(), 6); + _hexagonTargetLayout.getGOTSymAddr(), 6); break; case R_HEX_GOTREL_16_X: case R_HEX_GOTREL_11_X: - relocHexGOTRELUnsigned(location, relocVAddress, targetVAddress, ref.addend(), - _targetHandler.getGOTSymAddr()); + relocHexGOTRELUnsigned(location, relocVAddress, targetVAddress, + ref.addend(), _hexagonTargetLayout.getGOTSymAddr()); break; default : { @@ -349,4 +356,4 @@ error_code HexagonTargetRelocationHandler::applyRelocation( return error_code::success(); } -
\ No newline at end of file + diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.h b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.h index 85eba3595cf..191a1a0243b 100644 --- a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.h +++ b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.h @@ -18,23 +18,21 @@ namespace elf { class HexagonLinkingContext; class HexagonTargetHandler; -template <class HexagonELFType> class HexagonTargetLayout; class HexagonTargetRelocationHandler LLVM_FINAL : public TargetRelocationHandler<HexagonELFType> { public: - HexagonTargetRelocationHandler( - const HexagonLinkingContext &context, const HexagonTargetHandler &tH, - const HexagonTargetLayout<HexagonELFType> &layout) - : _targetHandler(tH), _targetLayout(layout) {} + HexagonTargetRelocationHandler(HexagonLinkingContext &context, + HexagonTargetLayout<HexagonELFType> &layout) + : _hexagonLinkingContext(context), _hexagonTargetLayout(layout) {} - virtual error_code - applyRelocation(ELFWriter &, llvm::FileOutputBuffer &, - const lld::AtomLayout &, const Reference &) const; + virtual error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &, + const lld::AtomLayout &, + const Reference &) const; private: - const HexagonTargetHandler &_targetHandler; - const HexagonTargetLayout<HexagonELFType> &_targetLayout; + HexagonLinkingContext &_hexagonLinkingContext LLVM_ATTRIBUTE_UNUSED; + HexagonTargetLayout<HexagonELFType> &_hexagonTargetLayout; }; } // elf } // lld diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonSectionChunks.h b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonSectionChunks.h index c54beaeadcf..a33d0534793 100644 --- a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonSectionChunks.h +++ b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonSectionChunks.h @@ -6,14 +6,13 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -#ifndef LLD_READER_WRITER_ELF_HEXAGON_HEXAGON_SECTION_CHUNKS_H -#define LLD_READER_WRITER_ELF_HEXAGON_HEXAGON_SECTION_CHUNKS_H +#ifndef HEXAGON_SECTION_CHUNKS_H +#define HEXAGON_SECTION_CHUNKS_H #include "HexagonTargetHandler.h" namespace lld { namespace elf { -typedef llvm::object::ELFType<llvm::support::little, 2, false> HexagonELFType; template <typename ELFT> class HexagonTargetLayout; class HexagonLinkingContext; diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp index 6edd214f0c5..a7481a871d0 100644 --- a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp +++ b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +#include "HexagonExecutableWriter.h" +#include "HexagonDynamicLibraryWriter.h" #include "HexagonTargetHandler.h" #include "HexagonLinkingContext.h" @@ -17,11 +19,28 @@ using namespace llvm::ELF; using llvm::makeArrayRef; HexagonTargetHandler::HexagonTargetHandler(HexagonLinkingContext &context) - : DefaultTargetHandler(context), _targetLayout(context), - _relocationHandler(context, *this, _targetLayout), - _hexagonRuntimeFile(new HexagonRuntimeFile<HexagonELFType>(context)) {} - -namespace { + : DefaultTargetHandler(context), _hexagonLinkingContext(context), + _hexagonRuntimeFile(new HexagonRuntimeFile<HexagonELFType>(context)), + _hexagonTargetLayout(new HexagonTargetLayout<HexagonELFType>(context)), + _hexagonRelocationHandler(new HexagonTargetRelocationHandler( + context, *_hexagonTargetLayout.get())) {} + +std::unique_ptr<Writer> HexagonTargetHandler::getWriter() { + switch (_hexagonLinkingContext.getOutputELFType()) { + case llvm::ELF::ET_EXEC: + return std::unique_ptr<Writer>( + new elf::HexagonExecutableWriter<HexagonELFType>( + _hexagonLinkingContext, *_hexagonTargetLayout.get())); + case llvm::ELF::ET_DYN: + return std::unique_ptr<Writer>( + new elf::HexagonDynamicLibraryWriter<HexagonELFType>( + _hexagonLinkingContext, *_hexagonTargetLayout.get())); + case llvm::ELF::ET_REL: + llvm_unreachable("TODO: support -r mode"); + default: + llvm_unreachable("unsupported output type"); + } +} using namespace llvm::ELF; @@ -297,7 +316,6 @@ public: return error_code::success(); } }; -} // end anonymous namespace void elf::HexagonLinkingContext::addPasses(PassManager &pm) { if (isDynamic()) diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h index 4052bed4d9a..35417914c21 100644 --- a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h +++ b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLD_READER_WRITER_ELF_HEXAGON_HEXAGON_TARGET_HANDLER_H -#define LLD_READER_WRITER_ELF_HEXAGON_HEXAGON_TARGET_HANDLER_H +#ifndef HEXAGON_TARGET_HANDLER_H +#define HEXAGON_TARGET_HANDLER_H #include "DefaultTargetHandler.h" #include "HexagonExecutableAtoms.h" @@ -25,14 +25,14 @@ class HexagonLinkingContext; /// \brief TargetLayout for Hexagon template <class HexagonELFType> class HexagonTargetLayout LLVM_FINAL : public TargetLayout<HexagonELFType> { - public: enum HexagonSectionOrder { ORDER_SDATA = 205 }; HexagonTargetLayout(const HexagonLinkingContext &hti) - : TargetLayout<HexagonELFType>(hti), _sdataSection(nullptr) { + : TargetLayout<HexagonELFType>(hti), _sdataSection(nullptr), + _gotSymAtom(nullptr), _cachedGotSymAtom(false) { _sdataSection = new (_alloc) SDataSection<HexagonELFType>(hti); } @@ -84,9 +84,22 @@ public: return _sdataSection; } + uint64_t getGOTSymAddr() { + if (!_cachedGotSymAtom) { + auto gotAtomIter = this->findAbsoluteAtom("_GLOBAL_OFFSET_TABLE_"); + _gotSymAtom = (*gotAtomIter); + _cachedGotSymAtom = true; + } + if (_gotSymAtom) + return _gotSymAtom->_virtualAddr; + return 0; + } + private: llvm::BumpPtrAllocator _alloc; SDataSection<HexagonELFType> *_sdataSection; + AtomLayout *_gotSymAtom; + bool _cachedGotSymAtom; }; /// \brief TargetHandler for Hexagon @@ -97,64 +110,12 @@ public: virtual void registerRelocationNames(Registry ®istry); - bool doesOverrideELFHeader() { return true; } - - void setELFHeader(ELFHeader<HexagonELFType> *elfHeader) { - elfHeader->e_ident(llvm::ELF::EI_VERSION, 1); - elfHeader->e_ident(llvm::ELF::EI_OSABI, 0); - elfHeader->e_version(1); - elfHeader->e_flags(0x3); - } - - virtual HexagonTargetLayout<HexagonELFType> &targetLayout() { - return _targetLayout; - } - virtual const HexagonTargetRelocationHandler &getRelocationHandler() const { - return _relocationHandler; - } - - void addDefaultAtoms() { - _hexagonRuntimeFile->addAbsoluteAtom("_SDA_BASE_"); - if (_context.isDynamic()) { - _hexagonRuntimeFile->addAbsoluteAtom("_GLOBAL_OFFSET_TABLE_"); - _hexagonRuntimeFile->addAbsoluteAtom("_DYNAMIC"); - } - } - - virtual bool - createImplicitFiles(std::vector<std::unique_ptr<File> > &result) { - // Add the default atoms as defined for hexagon - addDefaultAtoms(); - result.push_back(std::move(_hexagonRuntimeFile)); - return true; - } - - void finalizeSymbolValues() { - auto sdabaseAtomIter = _targetLayout.findAbsoluteAtom("_SDA_BASE_"); - (*sdabaseAtomIter)->_virtualAddr = - _targetLayout.getSDataSection()->virtualAddr(); - if (_context.isDynamic()) { - auto gotAtomIter = - _targetLayout.findAbsoluteAtom("_GLOBAL_OFFSET_TABLE_"); - _gotSymAtom = (*gotAtomIter); - auto gotpltSection = _targetLayout.findOutputSection(".got.plt"); - if (gotpltSection) - _gotSymAtom->_virtualAddr = gotpltSection->virtualAddr(); - else - _gotSymAtom->_virtualAddr = 0; - auto dynamicAtomIter = _targetLayout.findAbsoluteAtom("_DYNAMIC"); - auto dynamicSection = _targetLayout.findOutputSection(".dynamic"); - if (dynamicSection) - (*dynamicAtomIter)->_virtualAddr = dynamicSection->virtualAddr(); - else - (*dynamicAtomIter)->_virtualAddr = 0; - } + return *(_hexagonRelocationHandler.get()); } - uint64_t getGOTSymAddr() const { - if (!_gotSymAtom) return 0; - return _gotSymAtom->_virtualAddr; + virtual HexagonTargetLayout<HexagonELFType> &getTargetLayout() { + return *(_hexagonTargetLayout.get()); } virtual std::unique_ptr<Reader> getObjReader(bool atomizeStrings) { @@ -165,13 +126,15 @@ public: return std::unique_ptr<Reader>(new HexagonELFDSOReader(useShlibUndefines)); } + virtual std::unique_ptr<Writer> getWriter(); + private: + llvm::BumpPtrAllocator _alloc; static const Registry::KindStrings kindStrings[]; - - HexagonTargetLayout<HexagonELFType> _targetLayout; - HexagonTargetRelocationHandler _relocationHandler; + HexagonLinkingContext &_hexagonLinkingContext; std::unique_ptr<HexagonRuntimeFile<HexagonELFType> > _hexagonRuntimeFile; - AtomLayout *_gotSymAtom; + std::unique_ptr<HexagonTargetLayout<HexagonELFType>> _hexagonTargetLayout; + std::unique_ptr<HexagonTargetRelocationHandler> _hexagonRelocationHandler; }; } // end namespace elf } // end namespace lld diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsDynamicLibraryWriter.h b/lld/lib/ReaderWriter/ELF/Mips/MipsDynamicLibraryWriter.h new file mode 100644 index 00000000000..70598520d7d --- /dev/null +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsDynamicLibraryWriter.h @@ -0,0 +1,102 @@ +//===- lib/ReaderWriter/ELF/Mips/MipsDynamicLibraryWriter.h ---------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#ifndef MIPS_DYNAMIC_LIBRARY_WRITER_H +#define MIPS_DYNAMIC_LIBRARY_WRITER_H + +#include "DynamicLibraryWriter.h" +#include "MipsELFWriters.h" +#include "MipsLinkingContext.h" + +namespace lld { +namespace elf { + +template <typename ELFT> class MipsTargetLayout; + +template <class ELFT> +class MipsDynamicLibraryWriter : public DynamicLibraryWriter<ELFT>, + public MipsELFWriter<ELFT> { +public: + MipsDynamicLibraryWriter(MipsLinkingContext &context, + MipsTargetLayout<ELFT> &layout); + +protected: + // Add any runtime files and their atoms to the output + virtual bool createImplicitFiles(std::vector<std::unique_ptr<File>> &); + + virtual void finalizeDefaultAtomValues(); + + virtual error_code setELFHeader() { + DynamicLibraryWriter<ELFT>::setELFHeader(); + MipsELFWriter<ELFT>::setELFHeader(*this->_elfHeader); + return error_code::success(); + } + + LLD_UNIQUE_BUMP_PTR(DynamicTable<ELFT>) createDynamicTable(); + + LLD_UNIQUE_BUMP_PTR(DynamicSymbolTable<ELFT>) createDynamicSymbolTable(); + +private: + void addDefaultAtoms() { + if (this->_context.isDynamic()) { + _mipsRuntimeFile->addAbsoluteAtom("_GLOBAL_OFFSET_TABLE_"); + _mipsRuntimeFile->addAbsoluteAtom("_gp"); + _mipsRuntimeFile->addAbsoluteAtom("_gp_disp"); + } + } + + std::unique_ptr<MipsRuntimeFile<ELFT>> _mipsRuntimeFile; + MipsLinkingContext &_mipsContext; + MipsTargetLayout<Mips32ElELFType> &_mipsTargetLayout; +}; + +template <class ELFT> +MipsDynamicLibraryWriter<ELFT>::MipsDynamicLibraryWriter( + MipsLinkingContext &context, MipsTargetLayout<ELFT> &layout) + : DynamicLibraryWriter<ELFT>(context, layout), + MipsELFWriter<ELFT>(context, layout), + _mipsRuntimeFile(new MipsRuntimeFile<ELFT>(context)), + _mipsContext(context), _mipsTargetLayout(layout) {} + +template <class ELFT> +bool MipsDynamicLibraryWriter<ELFT>::createImplicitFiles( + std::vector<std::unique_ptr<File>> &result) { + DynamicLibraryWriter<ELFT>::createImplicitFiles(result); + // Add the default atoms as defined for mips + addDefaultAtoms(); + result.push_back(std::move(_mipsRuntimeFile)); + return true; +} + +template <class ELFT> +void MipsDynamicLibraryWriter<ELFT>::finalizeDefaultAtomValues() { + // Finalize the atom values that are part of the parent. + DynamicLibraryWriter<ELFT>::finalizeDefaultAtomValues(); + MipsELFWriter<ELFT>::finalizeMipsRuntimeAtomValues(); +} + +/// \brief create dynamic table +template <class ELFT> +LLD_UNIQUE_BUMP_PTR(DynamicTable<ELFT>) + MipsDynamicLibraryWriter<ELFT>::createDynamicTable() { + return LLD_UNIQUE_BUMP_PTR(DynamicTable<ELFT>)(new ( + this->_alloc) MipsDynamicTable(_mipsContext, _mipsTargetLayout)); +} + +/// \brief create dynamic symbol table +template <class ELFT> +LLD_UNIQUE_BUMP_PTR(DynamicSymbolTable<ELFT>) + MipsDynamicLibraryWriter<ELFT>::createDynamicSymbolTable() { + return LLD_UNIQUE_BUMP_PTR(DynamicSymbolTable<ELFT>)(new ( + this->_alloc) MipsDynamicSymbolTable(_mipsContext, _mipsTargetLayout)); +} + +} // namespace elf +} // namespace lld + +#endif // MIPS_DYNAMIC_LIBRARY_WRITER_H diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsELFWriters.h b/lld/lib/ReaderWriter/ELF/Mips/MipsELFWriters.h new file mode 100644 index 00000000000..4414a123754 --- /dev/null +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsELFWriters.h @@ -0,0 +1,75 @@ +//===- lib/ReaderWriter/ELF/Mips/MipsELFWriters.h -------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef MIPS_ELF_WRITERS_H +#define MIPS_ELF_WRITERS_H + +#include "MipsLinkingContext.h" +#include "OutputELFWriter.h" + +namespace lld { +namespace elf { + +template <class ELFT> class MipsTargetLayout; + +template <typename ELFT> class MipsELFWriter { +public: + MipsELFWriter(MipsLinkingContext &context, + MipsTargetLayout<ELFT> &targetLayout) + : _mipsLinkingContext(context), _mipsTargetLayout(targetLayout) {} + +protected: + bool setELFHeader(ELFHeader<ELFT> &elfHeader) { + elfHeader.e_version(1); + elfHeader.e_ident(llvm::ELF::EI_VERSION, llvm::ELF::EV_CURRENT); + elfHeader.e_ident(llvm::ELF::EI_OSABI, llvm::ELF::ELFOSABI_NONE); + if (_mipsTargetLayout.findOutputSection(".got.plt")) + elfHeader.e_ident(llvm::ELF::EI_ABIVERSION, 1); + else + elfHeader.e_ident(llvm::ELF::EI_ABIVERSION, 0); + + // FIXME (simon): Read elf flags from all inputs, check compatibility, + // merge them and write result here. + uint32_t flags = llvm::ELF::EF_MIPS_NOREORDER | llvm::ELF::EF_MIPS_ABI_O32 | + llvm::ELF::EF_MIPS_CPIC | llvm::ELF::EF_MIPS_ARCH_32R2; + if (_mipsLinkingContext.getOutputELFType() == llvm::ELF::ET_DYN) + flags |= EF_MIPS_PIC; + elfHeader.e_flags(flags); + return true; + } + + void finalizeMipsRuntimeAtomValues() { + if (_mipsLinkingContext.isDynamic()) { + auto gotSection = _mipsTargetLayout.findOutputSection(".got"); + auto got = gotSection ? gotSection->virtualAddr() : 0; + auto gp = gotSection ? got + _mipsTargetLayout.getGPOffset() : 0; + + auto gotAtomIter = + _mipsTargetLayout.findAbsoluteAtom("_GLOBAL_OFFSET_TABLE_"); + assert(gotAtomIter != _mipsTargetLayout.absoluteAtoms().end()); + (*gotAtomIter)->_virtualAddr = got; + + auto gpAtomIter = _mipsTargetLayout.findAbsoluteAtom("_gp"); + assert(gpAtomIter != _mipsTargetLayout.absoluteAtoms().end()); + (*gpAtomIter)->_virtualAddr = gp; + + AtomLayout *gpAtom = _mipsTargetLayout.getGP(); + assert(gpAtom != nullptr); + gpAtom->_virtualAddr = gp; + } + } + +private: + MipsLinkingContext &_mipsLinkingContext LLVM_ATTRIBUTE_UNUSED; + MipsTargetLayout<ELFT> &_mipsTargetLayout; +}; + +} // elf +} // lld +#endif // MIPS_ELF_WRITERS_H diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsExecutableWriter.h b/lld/lib/ReaderWriter/ELF/Mips/MipsExecutableWriter.h new file mode 100644 index 00000000000..9e211258ba1 --- /dev/null +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsExecutableWriter.h @@ -0,0 +1,102 @@ +//===- lib/ReaderWriter/ELF/Mips/MipsExecutableWriter.h -------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#ifndef MIPS_EXECUTABLE_WRITER_H +#define MIPS_EXECUTABLE_WRITER_H + +#include "ExecutableWriter.h" +#include "MipsELFWriters.h" +#include "MipsLinkingContext.h" + +namespace lld { +namespace elf { + +template <typename ELFT> class MipsTargetLayout; + +template <class ELFT> +class MipsExecutableWriter : public ExecutableWriter<ELFT>, + public MipsELFWriter<ELFT> { +public: + MipsExecutableWriter(MipsLinkingContext &context, + MipsTargetLayout<ELFT> &layout); + +protected: + // Add any runtime files and their atoms to the output + virtual bool createImplicitFiles(std::vector<std::unique_ptr<File>> &); + + virtual void finalizeDefaultAtomValues(); + + virtual error_code setELFHeader() { + ExecutableWriter<ELFT>::setELFHeader(); + MipsELFWriter<ELFT>::setELFHeader(*this->_elfHeader); + return error_code::success(); + } + + LLD_UNIQUE_BUMP_PTR(DynamicTable<ELFT>) createDynamicTable(); + + LLD_UNIQUE_BUMP_PTR(DynamicSymbolTable<ELFT>) createDynamicSymbolTable(); + +private: + void addDefaultAtoms() { + if (this->_context.isDynamic()) { + _mipsRuntimeFile->addAbsoluteAtom("_GLOBAL_OFFSET_TABLE_"); + _mipsRuntimeFile->addAbsoluteAtom("_gp"); + _mipsRuntimeFile->addAbsoluteAtom("_gp_disp"); + } + } + + std::unique_ptr<MipsRuntimeFile<ELFT>> _mipsRuntimeFile; + MipsLinkingContext &_mipsContext; + MipsTargetLayout<Mips32ElELFType> &_mipsTargetLayout; +}; + +template <class ELFT> +MipsExecutableWriter<ELFT>::MipsExecutableWriter(MipsLinkingContext &context, + MipsTargetLayout<ELFT> &layout) + : ExecutableWriter<ELFT>(context, layout), + MipsELFWriter<ELFT>(context, layout), + _mipsRuntimeFile(new MipsRuntimeFile<ELFT>(context)), + _mipsContext(context), _mipsTargetLayout(layout) {} + +template <class ELFT> +bool MipsExecutableWriter<ELFT>::createImplicitFiles( + std::vector<std::unique_ptr<File>> &result) { + ExecutableWriter<ELFT>::createImplicitFiles(result); + // Add the default atoms as defined for mips + addDefaultAtoms(); + result.push_back(std::move(_mipsRuntimeFile)); + return true; +} + +template <class ELFT> +void MipsExecutableWriter<ELFT>::finalizeDefaultAtomValues() { + // Finalize the atom values that are part of the parent. + ExecutableWriter<ELFT>::finalizeDefaultAtomValues(); + MipsELFWriter<ELFT>::finalizeMipsRuntimeAtomValues(); +} + +/// \brief create dynamic table +template <class ELFT> +LLD_UNIQUE_BUMP_PTR(DynamicTable<ELFT>) + MipsExecutableWriter<ELFT>::createDynamicTable() { + return LLD_UNIQUE_BUMP_PTR(DynamicTable<ELFT>)(new ( + this->_alloc) MipsDynamicTable(_mipsContext, _mipsTargetLayout)); +} + +/// \brief create dynamic symbol table +template <class ELFT> +LLD_UNIQUE_BUMP_PTR(DynamicSymbolTable<ELFT>) + MipsExecutableWriter<ELFT>::createDynamicSymbolTable() { + return LLD_UNIQUE_BUMP_PTR(DynamicSymbolTable<ELFT>)(new ( + this->_alloc) MipsDynamicSymbolTable(_mipsContext, _mipsTargetLayout)); +} + +} // namespace elf +} // namespace lld + +#endif // MIPS_EXECUTABLE_WRITER_H diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp b/lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp index 280943720f8..43578d5b4b0 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp @@ -19,17 +19,6 @@ MipsLinkingContext::MipsLinkingContext(llvm::Triple triple) : ELFLinkingContext(triple, std::unique_ptr<TargetHandlerBase>( new MipsTargetHandler(*this))) {} -MipsTargetLayout<Mips32ElELFType> &MipsLinkingContext::getTargetLayout() { - auto &layout = getTargetHandler<Mips32ElELFType>().targetLayout(); - return static_cast<MipsTargetLayout<Mips32ElELFType> &>(layout); -} - -const MipsTargetLayout<Mips32ElELFType> & -MipsLinkingContext::getTargetLayout() const { - auto &layout = getTargetHandler<Mips32ElELFType>().targetLayout(); - return static_cast<MipsTargetLayout<Mips32ElELFType> &>(layout); -} - bool MipsLinkingContext::isLittleEndian() const { return Mips32ElELFType::TargetEndianness == llvm::support::little; } diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp b/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp index 44153deeaf7..8f64fcee3fe 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp @@ -112,10 +112,6 @@ void relocLldLo16(uint8_t *location, uint64_t S) { } // end anon namespace -MipsTargetRelocationHandler::MipsTargetRelocationHandler( - const MipsLinkingContext &context, const MipsTargetHandler &handler) - : _targetHandler(handler) {} - MipsTargetRelocationHandler::~MipsTargetRelocationHandler() { assert(_pairedRelocations.empty()); } @@ -132,7 +128,7 @@ MipsTargetRelocationHandler::savePairedRelocation(const lld::AtomLayout &atom, void MipsTargetRelocationHandler::applyPairedRelocations( ELFWriter &writer, llvm::FileOutputBuffer &buf, const lld::AtomLayout &atom, - int64_t loAddend) const { + int64_t gpAddr, int64_t loAddend) const { auto pi = _pairedRelocations.find(&atom); if (pi == _pairedRelocations.end()) return; @@ -150,13 +146,11 @@ void MipsTargetRelocationHandler::applyPairedRelocations( assert(ri->kindArch() == Reference::KindArch::Mips); switch (ri->kindValue()) { case R_MIPS_HI16: - relocHi16(location, relocVAddress, targetVAddress, ahl, - _targetHandler.getGPDispSymAddr(), + relocHi16(location, relocVAddress, targetVAddress, ahl, gpAddr, ri->target()->name() == "_gp_disp"); break; case R_MIPS_GOT16: - relocGOT16(location, relocVAddress, targetVAddress, ahl, - _targetHandler.getGPDispSymAddr()); + relocGOT16(location, relocVAddress, targetVAddress, ahl, gpAddr); break; default: llvm_unreachable("Unknown type of paired relocation."); @@ -169,6 +163,9 @@ void MipsTargetRelocationHandler::applyPairedRelocations( error_code MipsTargetRelocationHandler::applyRelocation( ELFWriter &writer, llvm::FileOutputBuffer &buf, const lld::AtomLayout &atom, const Reference &ref) const { + AtomLayout *gpAtom = _mipsTargetLayout.getGP(); + uint64_t gpAddr = gpAtom ? gpAtom->_virtualAddr : 0; + uint8_t *atomContent = buf.getBufferStart() + atom._fileOffset; uint8_t *location = atomContent + ref.offsetInAtom(); uint64_t targetVAddress = writer.addressOfAtom(ref.target()); @@ -191,16 +188,14 @@ error_code MipsTargetRelocationHandler::applyRelocation( break; case R_MIPS_LO16: relocLo16(location, relocVAddress, targetVAddress, calcAHL(0, ref.addend()), - _targetHandler.getGPDispSymAddr(), - ref.target()->name() == "_gp_disp"); - applyPairedRelocations(writer, buf, atom, ref.addend()); + gpAddr, ref.target()->name() == "_gp_disp"); + applyPairedRelocations(writer, buf, atom, gpAddr, ref.addend()); break; case R_MIPS_GOT16: savePairedRelocation(atom, ref); break; case R_MIPS_CALL16: - relocCall16(location, relocVAddress, targetVAddress, ref.addend(), - _targetHandler.getGPDispSymAddr()); + relocCall16(location, relocVAddress, targetVAddress, ref.addend(), gpAddr); break; case R_MIPS_JALR: // We do not do JALR optimization now. @@ -212,8 +207,7 @@ error_code MipsTargetRelocationHandler::applyRelocation( // Do nothing. break; case LLD_R_MIPS_GLOBAL_GOT16: - relocGOT16(location, relocVAddress, targetVAddress, ref.addend(), - _targetHandler.getGPDispSymAddr()); + relocGOT16(location, relocVAddress, targetVAddress, ref.addend(), gpAddr); break; case LLD_R_MIPS_GLOBAL_26: reloc26(location, relocVAddress, targetVAddress, false); diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.h b/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.h index d2d9155d3df..80835dbc8dd 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.h +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.h @@ -19,8 +19,9 @@ class MipsTargetHandler; class MipsTargetRelocationHandler LLVM_FINAL : public TargetRelocationHandler<Mips32ElELFType> { public: - MipsTargetRelocationHandler(const MipsLinkingContext &context, - const MipsTargetHandler &handler); + MipsTargetRelocationHandler(MipsLinkingContext &context, + MipsTargetLayout<Mips32ElELFType> &layout) + : _mipsLinkingContext(context), _mipsTargetLayout(layout) {} ~MipsTargetRelocationHandler(); @@ -29,8 +30,6 @@ public: const Reference &) const; private: - const MipsTargetHandler &_targetHandler; - typedef std::vector<const Reference *> PairedRelocationsT; typedef std::unordered_map<const lld::AtomLayout *, PairedRelocationsT> PairedRelocationMapT; @@ -40,8 +39,11 @@ private: void savePairedRelocation(const lld::AtomLayout &atom, const Reference &ref) const; void applyPairedRelocations(ELFWriter &writer, llvm::FileOutputBuffer &buf, - const lld::AtomLayout &atom, + const lld::AtomLayout &atom, int64_t gpAddr, int64_t loAddend) const; + + MipsLinkingContext &_mipsLinkingContext LLVM_ATTRIBUTE_UNUSED; + MipsTargetLayout<Mips32ElELFType> &_mipsTargetLayout; }; } // elf diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp b/lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp index 601c9bf0723..be3d1e466cb 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp @@ -10,201 +10,35 @@ #include "ELFFile.h" #include "MipsLinkingContext.h" #include "MipsTargetHandler.h" +#include "MipsExecutableWriter.h" +#include "MipsDynamicLibraryWriter.h" using namespace lld; using namespace elf; -namespace { - -class MipsDynamicSymbolTable : public DynamicSymbolTable<Mips32ElELFType> { -public: - MipsDynamicSymbolTable(const MipsLinkingContext &context) - : DynamicSymbolTable<Mips32ElELFType>( - context, ".dynsym", - DefaultLayout<Mips32ElELFType>::ORDER_DYNAMIC_SYMBOLS), - _layout(context.getTargetLayout()) {} - - virtual void sortSymbols() { - std::stable_sort(_symbolTable.begin(), _symbolTable.end(), - [this](const SymbolEntry &A, const SymbolEntry &B) { - if (A._symbol.getBinding() != STB_GLOBAL && - B._symbol.getBinding() != STB_GLOBAL) - return A._symbol.getBinding() < B._symbol.getBinding(); - - return _layout.getGOTSection().compare(A._atom, B._atom); - }); - } - -private: - const MipsTargetLayout<Mips32ElELFType> &_layout; -}; - -class MipsDynamicTable : public DynamicTable<Mips32ElELFType> { -public: - MipsDynamicTable(MipsLinkingContext &context) - : DynamicTable<Mips32ElELFType>( - context, ".dynamic", DefaultLayout<Mips32ElELFType>::ORDER_DYNAMIC), - _layout(context.getTargetLayout()) {} - - virtual void createDefaultEntries() { - DynamicTable<Mips32ElELFType>::createDefaultEntries(); - - Elf_Dyn dyn; - - // Version id for the Runtime Linker Interface. - dyn.d_un.d_val = 1; - dyn.d_tag = DT_MIPS_RLD_VERSION; - addEntry(dyn); - - // MIPS flags. - dyn.d_un.d_val = RHF_NOTPOT; - dyn.d_tag = DT_MIPS_FLAGS; - addEntry(dyn); - - // The base address of the segment. - dyn.d_un.d_ptr = 0; - dyn.d_tag = DT_MIPS_BASE_ADDRESS; - _dt_baseaddr = addEntry(dyn); - - // Number of local global offset table entries. - dyn.d_un.d_val = 0; - dyn.d_tag = DT_MIPS_LOCAL_GOTNO; - _dt_localgot = addEntry(dyn); - - // Number of entries in the .dynsym section. - dyn.d_un.d_val = 0; - dyn.d_tag = DT_MIPS_SYMTABNO; - _dt_symtabno = addEntry(dyn); - - // The index of the first dynamic symbol table entry that corresponds - // to an entry in the global offset table. - dyn.d_un.d_val = 0; - dyn.d_tag = DT_MIPS_GOTSYM; - _dt_gotsym = addEntry(dyn); - - // Address of the .got section. - dyn.d_un.d_val = 0; - dyn.d_tag = DT_PLTGOT; - _dt_pltgot = addEntry(dyn); - } - - virtual void updateDynamicTable() { - DynamicTable<Mips32ElELFType>::updateDynamicTable(); - - // Assign the minimum segment address to the DT_MIPS_BASE_ADDRESS tag. - auto baseAddr = std::numeric_limits<uint64_t>::max(); - for (auto si : _layout.segments()) - if (si->segmentType() != llvm::ELF::PT_NULL) - baseAddr = std::min(baseAddr, si->virtualAddr()); - _entries[_dt_baseaddr].d_un.d_val = baseAddr; - - auto &got = _layout.getGOTSection(); - - _entries[_dt_symtabno].d_un.d_val = getSymbolTable()->size(); - _entries[_dt_gotsym].d_un.d_val = - getSymbolTable()->size() - got.getGlobalCount(); - _entries[_dt_localgot].d_un.d_val = got.getLocalCount(); - _entries[_dt_pltgot].d_un.d_ptr = - _layout.findOutputSection(".got")->virtualAddr(); - } - -private: - MipsTargetLayout<Mips32ElELFType> &_layout; - - std::size_t _dt_symtabno; - std::size_t _dt_localgot; - std::size_t _dt_gotsym; - std::size_t _dt_pltgot; - std::size_t _dt_baseaddr; -}; -} +typedef llvm::object::ELFType<llvm::support::little, 2, false> Mips32ElELFType; MipsTargetHandler::MipsTargetHandler(MipsLinkingContext &context) - : DefaultTargetHandler(context), _targetLayout(context), - _relocationHandler(context, *this), _gpDispSymAtom(nullptr) {} - -uint64_t MipsTargetHandler::getGPDispSymAddr() const { - return _gpDispSymAtom ? _gpDispSymAtom->_virtualAddr : 0; -} - -bool MipsTargetHandler::doesOverrideELFHeader() { return true; } - -void MipsTargetHandler::setELFHeader(ELFHeader<Mips32ElELFType> *elfHeader) { - elfHeader->e_version(1); - - elfHeader->e_ident(llvm::ELF::EI_VERSION, llvm::ELF::EV_CURRENT); - elfHeader->e_ident(llvm::ELF::EI_OSABI, llvm::ELF::ELFOSABI_NONE); - if (_targetLayout.findOutputSection(".got.plt")) - elfHeader->e_ident(llvm::ELF::EI_ABIVERSION, 1); - else - elfHeader->e_ident(llvm::ELF::EI_ABIVERSION, 0); - - // FIXME (simon): Read elf flags from all inputs, check compatibility, - // merge them and write result here. - uint32_t flags = llvm::ELF::EF_MIPS_NOREORDER | llvm::ELF::EF_MIPS_ABI_O32 | - llvm::ELF::EF_MIPS_CPIC | llvm::ELF::EF_MIPS_ARCH_32R2; - if (_context.getOutputELFType() == llvm::ELF::ET_DYN) - flags |= EF_MIPS_PIC; - elfHeader->e_flags(flags); -} - -MipsTargetLayout<Mips32ElELFType> &MipsTargetHandler::targetLayout() { - return _targetLayout; -} - -const MipsTargetRelocationHandler & -MipsTargetHandler::getRelocationHandler() const { - return _relocationHandler; -} - -LLD_UNIQUE_BUMP_PTR(DynamicTable<Mips32ElELFType>) -MipsTargetHandler::createDynamicTable() { - return LLD_UNIQUE_BUMP_PTR(DynamicTable<Mips32ElELFType>)( - new (_alloc) MipsDynamicTable( - static_cast<MipsLinkingContext &>(_context))); -} - -LLD_UNIQUE_BUMP_PTR(DynamicSymbolTable<Mips32ElELFType>) -MipsTargetHandler::createDynamicSymbolTable() { - return LLD_UNIQUE_BUMP_PTR(DynamicSymbolTable<Mips32ElELFType>)( - new (_alloc) MipsDynamicSymbolTable( - static_cast<MipsLinkingContext &>(_context))); -} - -bool MipsTargetHandler::createImplicitFiles( - std::vector<std::unique_ptr<File>> &result) { - typedef CRuntimeFile<Mips32ElELFType> RFile; - auto file = std::unique_ptr<RFile>(new RFile(_context, "MIPS runtime file")); - - if (_context.isDynamic()) { - file->addAbsoluteAtom("_GLOBAL_OFFSET_TABLE_"); - file->addAbsoluteAtom("_gp"); - file->addAbsoluteAtom("_gp_disp"); - } - result.push_back(std::move(file)); - return true; -} - -void MipsTargetHandler::finalizeSymbolValues() { - DefaultTargetHandler<Mips32ElELFType>::finalizeSymbolValues(); - - if (_context.isDynamic()) { - auto gotSection = _targetLayout.findOutputSection(".got"); - auto got = gotSection ? gotSection->virtualAddr() : 0; - auto gp = gotSection ? got + _targetLayout.getGPOffset() : 0; - - auto gotAtomIter = _targetLayout.findAbsoluteAtom("_GLOBAL_OFFSET_TABLE_"); - assert(gotAtomIter != _targetLayout.absoluteAtoms().end()); - (*gotAtomIter)->_virtualAddr = got; - - auto gpAtomIter = _targetLayout.findAbsoluteAtom("_gp"); - assert(gpAtomIter != _targetLayout.absoluteAtoms().end()); - (*gpAtomIter)->_virtualAddr = gp; - - auto gpDispAtomIter = _targetLayout.findAbsoluteAtom("_gp_disp"); - assert(gpDispAtomIter != _targetLayout.absoluteAtoms().end()); - _gpDispSymAtom = (*gpDispAtomIter); - _gpDispSymAtom->_virtualAddr = gp; + : DefaultTargetHandler(context), _mipsLinkingContext(context), + _mipsRuntimeFile(new MipsRuntimeFile<Mips32ElELFType>(context)), + _mipsTargetLayout(new MipsTargetLayout<Mips32ElELFType>(context)), + _mipsRelocationHandler( + new MipsTargetRelocationHandler(context, *_mipsTargetLayout.get())) {} + +std::unique_ptr<Writer> MipsTargetHandler::getWriter() { + switch (_mipsLinkingContext.getOutputELFType()) { + case llvm::ELF::ET_EXEC: + return std::unique_ptr<Writer>( + new elf::MipsExecutableWriter<Mips32ElELFType>( + _mipsLinkingContext, *_mipsTargetLayout.get())); + case llvm::ELF::ET_DYN: + return std::unique_ptr<Writer>( + new elf::MipsDynamicLibraryWriter<Mips32ElELFType>( + _mipsLinkingContext, *_mipsTargetLayout.get())); + case llvm::ELF::ET_REL: + llvm_unreachable("TODO: support -r mode"); + default: + llvm_unreachable("unsupported output type"); } } diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h b/lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h index e5bf725966b..1cad6a40ccd 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h @@ -24,10 +24,8 @@ class MipsTargetLayout LLVM_FINAL : public TargetLayout<ELFType> { public: MipsTargetLayout(const MipsLinkingContext &ctx) : TargetLayout<ELFType>(ctx), - _gotSection(new (_alloc) MipsGOTSection<ELFType>(ctx)) {} - - /// \brief GP offset relative to .got section. - uint64_t getGPOffset() const { return 0x7FF0; } + _gotSection(new (_alloc) MipsGOTSection<ELFType>(ctx)), + _cachedGP(false) {} const MipsGOTSection<ELFType> &getGOTSection() const { return *_gotSection; } @@ -41,39 +39,162 @@ public: order); } + /// \brief GP offset relative to .got section. + uint64_t getGPOffset() const { return 0x7FF0; } + + /// \brief Get the cached value of the GP atom. + AtomLayout *getGP() { + if (!_cachedGP) { + auto gpAtomIter = this->findAbsoluteAtom("_gp_disp"); + _gp = *(gpAtomIter); + _cachedGP = true; + } + return _gp; + } + private: llvm::BumpPtrAllocator _alloc; MipsGOTSection<ELFType> *_gotSection; + AtomLayout *_gp; + bool _cachedGP; +}; + +/// \brief Mips Runtime file. +template <class ELFType> class MipsRuntimeFile : public CRuntimeFile<ELFType> { +public: + MipsRuntimeFile(const MipsLinkingContext &context) + : CRuntimeFile<ELFType>(context, "Mips runtime file") {} }; /// \brief TargetHandler for Mips class MipsTargetHandler LLVM_FINAL : public DefaultTargetHandler<Mips32ElELFType> { public: - MipsTargetHandler(MipsLinkingContext &targetInfo); - - uint64_t getGPDispSymAddr() const; - - virtual bool doesOverrideELFHeader(); - virtual void setELFHeader(ELFHeader<Mips32ElELFType> *elfHeader); - virtual MipsTargetLayout<Mips32ElELFType> &targetLayout(); - virtual const MipsTargetRelocationHandler &getRelocationHandler() const; - virtual LLD_UNIQUE_BUMP_PTR(DynamicTable<Mips32ElELFType>) - createDynamicTable(); - virtual LLD_UNIQUE_BUMP_PTR(DynamicSymbolTable<Mips32ElELFType>) - createDynamicSymbolTable(); - virtual bool createImplicitFiles(std::vector<std::unique_ptr<File>> &result); - virtual void finalizeSymbolValues(); + MipsTargetHandler(MipsLinkingContext &context); + + virtual MipsTargetLayout<Mips32ElELFType> &getTargetLayout() { + return *(_mipsTargetLayout.get()); + } + + virtual const MipsTargetRelocationHandler &getRelocationHandler() const { + return *(_mipsRelocationHandler.get()); + } + + virtual std::unique_ptr<Writer> getWriter(); + virtual void registerRelocationNames(Registry ®istry); private: static const Registry::KindStrings kindStrings[]; - llvm::BumpPtrAllocator _alloc; - MipsTargetLayout<Mips32ElELFType> _targetLayout; - MipsTargetRelocationHandler _relocationHandler; - AtomLayout *_gpDispSymAtom; + MipsLinkingContext &_mipsLinkingContext; + std::unique_ptr<MipsRuntimeFile<Mips32ElELFType>> _mipsRuntimeFile; + std::unique_ptr<MipsTargetLayout<Mips32ElELFType>> _mipsTargetLayout; + std::unique_ptr<MipsTargetRelocationHandler> _mipsRelocationHandler; }; +class MipsDynamicSymbolTable : public DynamicSymbolTable<Mips32ElELFType> { +public: + MipsDynamicSymbolTable(const MipsLinkingContext &context, + MipsTargetLayout<Mips32ElELFType> &layout) + : DynamicSymbolTable<Mips32ElELFType>( + context, layout, ".dynsym", + DefaultLayout<Mips32ElELFType>::ORDER_DYNAMIC_SYMBOLS), + _mipsTargetLayout(layout) {} + + virtual void sortSymbols() { + std::stable_sort(_symbolTable.begin(), _symbolTable.end(), + [this](const SymbolEntry &A, const SymbolEntry &B) { + if (A._symbol.getBinding() != STB_GLOBAL && + B._symbol.getBinding() != STB_GLOBAL) + return A._symbol.getBinding() < B._symbol.getBinding(); + + return _mipsTargetLayout.getGOTSection().compare(A._atom, B._atom); + }); + } + +private: + MipsTargetLayout<Mips32ElELFType> &_mipsTargetLayout; +}; + +class MipsDynamicTable : public DynamicTable<Mips32ElELFType> { +public: + MipsDynamicTable(MipsLinkingContext &context, + MipsTargetLayout<Mips32ElELFType> &layout) + : DynamicTable<Mips32ElELFType>( + context, layout, ".dynamic", + DefaultLayout<Mips32ElELFType>::ORDER_DYNAMIC), + _mipsTargetLayout(layout) {} + + virtual void createDefaultEntries() { + DynamicTable<Mips32ElELFType>::createDefaultEntries(); + + Elf_Dyn dyn; + + // Version id for the Runtime Linker Interface. + dyn.d_un.d_val = 1; + dyn.d_tag = DT_MIPS_RLD_VERSION; + addEntry(dyn); + + // MIPS flags. + dyn.d_un.d_val = RHF_NOTPOT; + dyn.d_tag = DT_MIPS_FLAGS; + addEntry(dyn); + + // The base address of the segment. + dyn.d_un.d_ptr = 0; + dyn.d_tag = DT_MIPS_BASE_ADDRESS; + _dt_baseaddr = addEntry(dyn); + + // Number of local global offset table entries. + dyn.d_un.d_val = 0; + dyn.d_tag = DT_MIPS_LOCAL_GOTNO; + _dt_localgot = addEntry(dyn); + + // Number of entries in the .dynsym section. + dyn.d_un.d_val = 0; + dyn.d_tag = DT_MIPS_SYMTABNO; + _dt_symtabno = addEntry(dyn); + + // The index of the first dynamic symbol table entry that corresponds + // to an entry in the global offset table. + dyn.d_un.d_val = 0; + dyn.d_tag = DT_MIPS_GOTSYM; + _dt_gotsym = addEntry(dyn); + + // Address of the .got section. + dyn.d_un.d_val = 0; + dyn.d_tag = DT_PLTGOT; + _dt_pltgot = addEntry(dyn); + } + + virtual void updateDynamicTable() { + DynamicTable<Mips32ElELFType>::updateDynamicTable(); + + // Assign the minimum segment address to the DT_MIPS_BASE_ADDRESS tag. + auto baseAddr = std::numeric_limits<uint64_t>::max(); + for (auto si : _mipsTargetLayout.segments()) + if (si->segmentType() != llvm::ELF::PT_NULL) + baseAddr = std::min(baseAddr, si->virtualAddr()); + _entries[_dt_baseaddr].d_un.d_val = baseAddr; + + auto &got = _mipsTargetLayout.getGOTSection(); + + _entries[_dt_symtabno].d_un.d_val = getSymbolTable()->size(); + _entries[_dt_gotsym].d_un.d_val = + getSymbolTable()->size() - got.getGlobalCount(); + _entries[_dt_localgot].d_un.d_val = got.getLocalCount(); + _entries[_dt_pltgot].d_un.d_ptr = + _mipsTargetLayout.findOutputSection(".got")->virtualAddr(); + } + +private: + std::size_t _dt_symtabno; + std::size_t _dt_localgot; + std::size_t _dt_gotsym; + std::size_t _dt_pltgot; + std::size_t _dt_baseaddr; + MipsTargetLayout<Mips32ElELFType> &_mipsTargetLayout; +}; } // end namespace elf } // end namespace lld diff --git a/lld/lib/ReaderWriter/ELF/OutputELFWriter.h b/lld/lib/ReaderWriter/ELF/OutputELFWriter.h index af19214f2e6..ab939b59500 100644 --- a/lld/lib/ReaderWriter/ELF/OutputELFWriter.h +++ b/lld/lib/ReaderWriter/ELF/OutputELFWriter.h @@ -26,6 +26,7 @@ using namespace llvm; using namespace llvm::object; template <class ELFT> class OutputELFWriter; +template <class ELFT> class TargetLayout; //===----------------------------------------------------------------------===// // OutputELFWriter Class @@ -41,7 +42,7 @@ public: typedef Elf_Sym_Impl<ELFT> Elf_Sym; typedef Elf_Dyn_Impl<ELFT> Elf_Dyn; - OutputELFWriter(const ELFLinkingContext &context); + OutputELFWriter(const ELFLinkingContext &context, TargetLayout<ELFT> &layout); protected: // build the sections that need to be created @@ -100,6 +101,13 @@ protected: // This is a hook for creating default dynamic entries virtual void createDefaultDynamicEntries() {} + /// \brief create dynamic table. + virtual LLD_UNIQUE_BUMP_PTR(DynamicTable<ELFT>) createDynamicTable(); + + /// \brief create dynamic symbol table. + virtual LLD_UNIQUE_BUMP_PTR(DynamicSymbolTable<ELFT>) + createDynamicSymbolTable(); + llvm::BumpPtrAllocator _alloc; const ELFLinkingContext &_context; @@ -107,7 +115,7 @@ protected: typedef llvm::DenseMap<const Atom *, uint64_t> AtomToAddress; AtomToAddress _atomToAddressMap; - TargetLayout<ELFT> *_layout; + TargetLayout<ELFT> &_layout; LLD_UNIQUE_BUMP_PTR(ELFHeader<ELFT>) _elfHeader; LLD_UNIQUE_BUMP_PTR(ProgramHeader<ELFT>) _programHeader; LLD_UNIQUE_BUMP_PTR(SymbolTable<ELFT>) _symtab; @@ -129,29 +137,29 @@ protected: // OutputELFWriter //===----------------------------------------------------------------------===// template <class ELFT> -OutputELFWriter<ELFT>::OutputELFWriter(const ELFLinkingContext &context) - : _context(context), _targetHandler(context.getTargetHandler<ELFT>()) { - _layout = &_targetHandler.targetLayout(); -} +OutputELFWriter<ELFT>::OutputELFWriter(const ELFLinkingContext &context, + TargetLayout<ELFT> &layout) + : _context(context), _targetHandler(context.getTargetHandler<ELFT>()), + _layout(layout) {} template <class ELFT> void OutputELFWriter<ELFT>::buildChunks(const File &file) { ScopedTask task(getDefaultDomain(), "buildChunks"); for (const DefinedAtom *definedAtom : file.defined()) { - _layout->addAtom(definedAtom); + _layout.addAtom(definedAtom); } for (const AbsoluteAtom *absoluteAtom : file.absolute()) - _layout->addAtom(absoluteAtom); + _layout.addAtom(absoluteAtom); } template <class ELFT> void OutputELFWriter<ELFT>::buildStaticSymbolTable(const File &file) { ScopedTask task(getDefaultDomain(), "buildStaticSymbolTable"); - for (auto sec : _layout->sections()) + for (auto sec : _layout.sections()) if (auto section = dyn_cast<AtomSection<ELFT>>(sec)) for (const auto &atom : section->atoms()) _symtab->addSymbol(atom->_atom, section->ordinal(), atom->_virtualAddr); - for (auto &atom : _layout->absoluteAtoms()) + for (auto &atom : _layout.absoluteAtoms()) _symtab->addSymbol(atom->_atom, ELF::SHN_ABS, atom->_virtualAddr); for (const UndefinedAtom *a : file.undefined()) _symtab->addSymbol(a, ELF::SHN_UNDEF); @@ -160,7 +168,7 @@ void OutputELFWriter<ELFT>::buildStaticSymbolTable(const File &file) { template <class ELFT> void OutputELFWriter<ELFT>::buildDynamicSymbolTable(const File &file) { ScopedTask task(getDefaultDomain(), "buildDynamicSymbolTable"); - for (auto sec : this->_layout->sections()) + for (auto sec : this->_layout.sections()) if (auto section = dyn_cast<AtomSection<ELFT>>(sec)) for (const auto &atom : section->atoms()) { const DefinedAtom *da = dyn_cast<const DefinedAtom>(atom->_atom); @@ -208,17 +216,17 @@ void OutputELFWriter<ELFT>::buildDynamicSymbolTable(const File &file) { template <class ELFT> void OutputELFWriter<ELFT>::buildAtomToAddressMap(const File &file) { ScopedTask task(getDefaultDomain(), "buildAtomToAddressMap"); - int64_t totalAbsAtoms = _layout->absoluteAtoms().size(); + int64_t totalAbsAtoms = _layout.absoluteAtoms().size(); int64_t totalUndefinedAtoms = file.undefined().size(); int64_t totalDefinedAtoms = 0; - for (auto sec : _layout->sections()) + for (auto sec : _layout.sections()) if (auto section = dyn_cast<AtomSection<ELFT> >(sec)) { totalDefinedAtoms += section->atoms().size(); for (const auto &atom : section->atoms()) _atomToAddressMap[atom->_atom] = atom->_virtualAddr; } // build the atomToAddressMap that contains absolute symbols too - for (auto &atom : _layout->absoluteAtoms()) + for (auto &atom : _layout.absoluteAtoms()) _atomToAddressMap[atom->_atom] = atom->_virtualAddr; // Set the total number of atoms in the symbol table, so that appropriate @@ -230,7 +238,7 @@ void OutputELFWriter<ELFT>::buildAtomToAddressMap(const File &file) { template<class ELFT> void OutputELFWriter<ELFT>::buildSectionHeaderTable() { ScopedTask task(getDefaultDomain(), "buildSectionHeaderTable"); - for (auto mergedSec : _layout->mergedSections()) { + for (auto mergedSec : _layout.mergedSections()) { if (mergedSec->kind() != Chunk<ELFT>::Kind::ELFSection && mergedSec->kind() != Chunk<ELFT>::Kind::AtomSection) continue; @@ -242,15 +250,15 @@ void OutputELFWriter<ELFT>::buildSectionHeaderTable() { template<class ELFT> void OutputELFWriter<ELFT>::assignSectionsWithNoSegments() { ScopedTask task(getDefaultDomain(), "assignSectionsWithNoSegments"); - for (auto mergedSec : _layout->mergedSections()) { + for (auto mergedSec : _layout.mergedSections()) { if (mergedSec->kind() != Chunk<ELFT>::Kind::ELFSection && mergedSec->kind() != Chunk<ELFT>::Kind::AtomSection) continue; if (!mergedSec->hasSegment()) _shdrtab->appendSection(mergedSec); } - _layout->assignOffsetsForMiscSections(); - for (auto sec : _layout->sections()) + _layout.assignOffsetsForMiscSections(); + for (auto sec : _layout.sections()) if (auto section = dyn_cast<Section<ELFT>>(sec)) if (!DefaultLayout<ELFT>::hasOutputSegment(section)) _shdrtab->updateSection(section); @@ -258,17 +266,15 @@ void OutputELFWriter<ELFT>::assignSectionsWithNoSegments() { template <class ELFT> bool OutputELFWriter<ELFT>::createImplicitFiles( - std::vector<std::unique_ptr<File> > &result) { - // Add all input Files that are defined by the target - _targetHandler.createImplicitFiles(result); + std::vector<std::unique_ptr<File>> &) { return true; } template <class ELFT> void OutputELFWriter<ELFT>::createDefaultSections() { _elfHeader.reset(new (_alloc) ELFHeader<ELFT>(_context)); _programHeader.reset(new (_alloc) ProgramHeader<ELFT>(_context)); - _layout->setHeader(_elfHeader.get()); - _layout->setProgramHeader(_programHeader.get()); + _layout.setHeader(_elfHeader.get()); + _layout.setProgramHeader(_programHeader.get()); _symtab.reset(new (_alloc) SymbolTable<ELFT>( _context, ".symtab", DefaultLayout<ELFT>::ORDER_SYMBOL_TABLE)); @@ -278,50 +284,67 @@ template <class ELFT> void OutputELFWriter<ELFT>::createDefaultSections() { _context, ".shstrtab", DefaultLayout<ELFT>::ORDER_SECTION_STRINGS)); _shdrtab.reset(new (_alloc) SectionHeader<ELFT>( _context, DefaultLayout<ELFT>::ORDER_SECTION_HEADERS)); - _layout->addSection(_symtab.get()); - _layout->addSection(_strtab.get()); - _layout->addSection(_shstrtab.get()); + _layout.addSection(_symtab.get()); + _layout.addSection(_strtab.get()); + _layout.addSection(_shstrtab.get()); _shdrtab->setStringSection(_shstrtab.get()); _symtab->setStringSection(_strtab.get()); - _layout->addSection(_shdrtab.get()); + _layout.addSection(_shdrtab.get()); - for (auto sec : _layout->sections()) { + for (auto sec : _layout.sections()) { if (sec->name() != ".eh_frame") continue; _ehFrameHeader.reset(new (_alloc) EHFrameHeader<ELFT>( - _context, ".eh_frame_hdr", DefaultLayout<ELFT>::ORDER_EH_FRAMEHDR)); - _layout->addSection(_ehFrameHeader.get()); + _context, ".eh_frame_hdr", _layout, + DefaultLayout<ELFT>::ORDER_EH_FRAMEHDR)); + _layout.addSection(_ehFrameHeader.get()); break; } if (_context.isDynamic()) { - _dynamicTable = std::move(_targetHandler.createDynamicTable()); + _dynamicTable = std::move(createDynamicTable()); _dynamicStringTable.reset(new (_alloc) StringTable<ELFT>( _context, ".dynstr", DefaultLayout<ELFT>::ORDER_DYNAMIC_STRINGS, true)); - _dynamicSymbolTable = std::move(_targetHandler.createDynamicSymbolTable()); + _dynamicSymbolTable = std::move(createDynamicSymbolTable()); _hashTable.reset(new (_alloc) HashSection<ELFT>( _context, ".hash", DefaultLayout<ELFT>::ORDER_HASH)); // Set the hash table in the dynamic symbol table so that the entries in the // hash table can be created _dynamicSymbolTable->setHashTable(_hashTable.get()); _hashTable->setSymbolTable(_dynamicSymbolTable.get()); - _layout->addSection(_dynamicTable.get()); - _layout->addSection(_dynamicStringTable.get()); - _layout->addSection(_dynamicSymbolTable.get()); - _layout->addSection(_hashTable.get()); + _layout.addSection(_dynamicTable.get()); + _layout.addSection(_dynamicStringTable.get()); + _layout.addSection(_dynamicSymbolTable.get()); + _layout.addSection(_hashTable.get()); _dynamicSymbolTable->setStringSection(_dynamicStringTable.get()); _dynamicTable->setSymbolTable(_dynamicSymbolTable.get()); _dynamicTable->setHashTable(_hashTable.get()); - if (_layout->hasDynamicRelocationTable()) - _layout->getDynamicRelocationTable() - ->setSymbolTable(_dynamicSymbolTable.get()); - if (_layout->hasPLTRelocationTable()) - _layout->getPLTRelocationTable()->setSymbolTable( + if (_layout.hasDynamicRelocationTable()) + _layout.getDynamicRelocationTable()->setSymbolTable( + _dynamicSymbolTable.get()); + if (_layout.hasPLTRelocationTable()) + _layout.getPLTRelocationTable()->setSymbolTable( _dynamicSymbolTable.get()); } +} - // give a chance for the target to add sections - _targetHandler.createDefaultSections(); +/// \brief create dynamic table +template <class ELFT> +LLD_UNIQUE_BUMP_PTR(DynamicTable<ELFT>) + OutputELFWriter<ELFT>::createDynamicTable() { + return LLD_UNIQUE_BUMP_PTR( + DynamicTable<ELFT>)(new (_alloc) DynamicTable<ELFT>( + this->_context, _layout, ".dynamic", DefaultLayout<ELFT>::ORDER_DYNAMIC)); +} + +/// \brief create dynamic symbol table +template <class ELFT> +LLD_UNIQUE_BUMP_PTR(DynamicSymbolTable<ELFT>) + OutputELFWriter<ELFT>::createDynamicSymbolTable() { + return LLD_UNIQUE_BUMP_PTR( + DynamicSymbolTable<ELFT>)(new (_alloc) DynamicSymbolTable<ELFT>( + this->_context, _layout, ".dynsym", + DefaultLayout<ELFT>::ORDER_DYNAMIC_SYMBOLS)); } template <class ELFT> @@ -334,7 +357,7 @@ error_code OutputELFWriter<ELFT>::buildOutput(const File &file) { createDefaultSections(); // Set the Layout - _layout->assignSectionsToSegments(); + _layout.assignSectionsToSegments(); // Create the dynamic table entries if (_context.isDynamic()) { @@ -344,10 +367,10 @@ error_code OutputELFWriter<ELFT>::buildOutput(const File &file) { // Call the preFlight callbacks to modify the sections and the atoms // contained in them, in anyway the targets may want - _layout->doPreFlight(); + _layout.doPreFlight(); - _layout->assignFileOffsets(); - _layout->assignVirtualAddress(); + _layout.assignFileOffsets(); + _layout.assignVirtualAddress(); // Finalize the default value of symbols that the linker adds finalizeDefaultAtomValues(); @@ -359,7 +382,7 @@ error_code OutputELFWriter<ELFT>::buildOutput(const File &file) { buildStaticSymbolTable(file); // Finalize the layout by calling the finalize() functions - _layout->finalize(); + _layout.finalize(); // build Section Header table buildSectionHeaderTable(); @@ -393,7 +416,7 @@ template <class ELFT> error_code OutputELFWriter<ELFT>::setELFHeader() { _elfHeader->e_shnum(_shdrtab->numHeaders()); _elfHeader->e_shstrndx(_shstrtab->ordinal()); uint64_t virtualAddr = 0; - _layout->findAtomAddrByName(_context.entrySymbolName(), virtualAddr); + _layout.findAtomAddrByName(_context.entrySymbolName(), virtualAddr); _elfHeader->e_entry(virtualAddr); return error_code::success(); @@ -420,11 +443,11 @@ error_code OutputELFWriter<ELFT>::writeOutput(const File &file, // HACK: We have to write out the header and program header here even though // they are a member of a segment because only sections are written in the // following loop. - _elfHeader->write(this, *buffer); - _programHeader->write(this, *buffer); + _elfHeader->write(this, _layout, *buffer); + _programHeader->write(this, _layout, *buffer); - for (auto section : _layout->sections()) - section->write(this, *buffer); + for (auto section : _layout.sections()) + section->write(this, _layout, *buffer); writeTask.end(); ScopedTask commitTask(getDefaultDomain(), "ELF Writer commit to disk"); diff --git a/lld/lib/ReaderWriter/ELF/PPC/PPCELFFile.h b/lld/lib/ReaderWriter/ELF/PPC/PPCELFFile.h new file mode 100644 index 00000000000..15ccb814e5f --- /dev/null +++ b/lld/lib/ReaderWriter/ELF/PPC/PPCELFFile.h @@ -0,0 +1,38 @@ +//===- lib/ReaderWriter/ELF/PPCELFFile.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_PPC_ELF_FILE_H +#define LLD_READER_WRITER_ELF_PPC_ELF_FILE_H + +#include "ELFReader.h" + +namespace lld { +namespace elf { + +class PPCLinkingContext; + +template <class ELFT> class PPCELFFile : public ELFFile<ELFT> { +public: + PPCELFFile(StringRef name) : ELFFile<ELFT>(name) {} + + PPCELFFile(std::unique_ptr<MemoryBuffer> mb, bool atomizeStrings, + TargetHandlerBase *handler, error_code &ec) + : ELFFile<ELFT>(std::move(mb), atomizeStrings, handler, ec) {} +}; + +template <class ELFT> class PPCDynamicFile : public DynamicFile<ELFT> { +public: + PPCDynamicFile(const PPCLinkingContext &context, StringRef name) + : DynamicFile<ELFT>(context, name) {} +}; + +} // elf +} // lld + +#endif // LLD_READER_WRITER_ELF_PPC_ELF_FILE_H diff --git a/lld/lib/ReaderWriter/ELF/PPC/PPCELFReader.h b/lld/lib/ReaderWriter/ELF/PPC/PPCELFReader.h new file mode 100644 index 00000000000..41d95f31615 --- /dev/null +++ b/lld/lib/ReaderWriter/ELF/PPC/PPCELFReader.h @@ -0,0 +1,81 @@ +//===- lib/ReaderWriter/ELF/PPCELFReader.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_PPC_ELF_READER_H +#define LLD_READER_WRITER_PPC_ELF_READER_H + +#include "ELFReader.h" +#include "PPCELFFile.h" + +namespace lld { +namespace elf { + +struct PPCDynamicFileCreateELFTraits { + typedef llvm::ErrorOr<std::unique_ptr<lld::SharedLibraryFile>> result_type; + + template <class ELFT> + static result_type create(std::unique_ptr<llvm::MemoryBuffer> mb, + bool useUndefines) { + return lld::elf::PPCDynamicFile<ELFT>::create(std::move(mb), useUndefines); + } +}; + +struct PPCELFFileCreateELFTraits { + typedef llvm::ErrorOr<std::unique_ptr<lld::File>> result_type; + + template <class ELFT> + static result_type create(std::unique_ptr<llvm::MemoryBuffer> mb, + bool atomizeStrings) { + return lld::elf::PPCELFFile<ELFT>::create(std::move(mb), atomizeStrings); + } +}; + +class PPCELFObjectReader : public ELFObjectReader { +public: + PPCELFObjectReader(bool atomizeStrings) : ELFObjectReader(atomizeStrings) {} + + virtual error_code + parseFile(std::unique_ptr<MemoryBuffer> &mb, const class Registry &, + std::vector<std::unique_ptr<File>> &result) const { + error_code ec; + std::size_t maxAlignment = + 1ULL << llvm::countTrailingZeros(uintptr_t(mb->getBufferStart())); + auto f = createELF<PPCELFFileCreateELFTraits>( + llvm::object::getElfArchType(&*mb), maxAlignment, std::move(mb), + _atomizeStrings); + if (!f) + return f; + result.push_back(std::move(*f)); + return error_code::success(); + } +}; + +class PPCELFDSOReader : public ELFDSOReader { +public: + PPCELFDSOReader(bool useUndefines) : ELFDSOReader(useUndefines) {} + + virtual error_code + parseFile(std::unique_ptr<MemoryBuffer> &mb, const class Registry &, + std::vector<std::unique_ptr<File>> &result) const { + std::size_t maxAlignment = + 1ULL << llvm::countTrailingZeros(uintptr_t(mb->getBufferStart())); + auto f = createELF<PPCDynamicFileCreateELFTraits>( + llvm::object::getElfArchType(&*mb), maxAlignment, std::move(mb), + _useUndefines); + if (!f) + return f; + result.push_back(std::move(*f)); + return error_code::success(); + } +}; + +} // namespace elf +} // namespace lld + +#endif // LLD_READER_WRITER_ELF_READER_H diff --git a/lld/lib/ReaderWriter/ELF/PPC/PPCTargetHandler.cpp b/lld/lib/ReaderWriter/ELF/PPC/PPCTargetHandler.cpp index d5a94803864..8f05bb9b6bc 100644 --- a/lld/lib/ReaderWriter/ELF/PPC/PPCTargetHandler.cpp +++ b/lld/lib/ReaderWriter/ELF/PPC/PPCTargetHandler.cpp @@ -63,15 +63,32 @@ error_code PPCTargetRelocationHandler::applyRelocation( return error_code::success(); } -PPCTargetHandler::PPCTargetHandler(PPCLinkingContext &targetInfo) - : DefaultTargetHandler(targetInfo), _relocationHandler(targetInfo), - _targetLayout(targetInfo) {} +PPCTargetHandler::PPCTargetHandler(PPCLinkingContext &context) + : DefaultTargetHandler(context), _ppcLinkingContext(context), + _ppcTargetLayout(new PPCTargetLayout<PPCELFType>(context)), + _ppcRelocationHandler( + new PPCTargetRelocationHandler(context, *_ppcTargetLayout.get())) {} void PPCTargetHandler::registerRelocationNames(Registry ®istry) { registry.addKindTable(Reference::KindNamespace::ELF, Reference::KindArch::PowerPC, kindStrings); } +std::unique_ptr<Writer> PPCTargetHandler::getWriter() { + switch (_ppcLinkingContext.getOutputELFType()) { + case llvm::ELF::ET_EXEC: + return std::unique_ptr<Writer>(new elf::ExecutableWriter<PPCELFType>( + _ppcLinkingContext, *_ppcTargetLayout.get())); + case llvm::ELF::ET_DYN: + return std::unique_ptr<Writer>(new elf::DynamicLibraryWriter<PPCELFType>( + _ppcLinkingContext, *_ppcTargetLayout.get())); + case llvm::ELF::ET_REL: + llvm_unreachable("TODO: support -r mode"); + default: + llvm_unreachable("unsupported output type"); + } +} + const Registry::KindStrings PPCTargetHandler::kindStrings[] = { LLD_KIND_STRING_ENTRY(R_PPC_NONE), LLD_KIND_STRING_ENTRY(R_PPC_ADDR32), diff --git a/lld/lib/ReaderWriter/ELF/PPC/PPCTargetHandler.h b/lld/lib/ReaderWriter/ELF/PPC/PPCTargetHandler.h index 5468874fb65..eba58bf328d 100644 --- a/lld/lib/ReaderWriter/ELF/PPC/PPCTargetHandler.h +++ b/lld/lib/ReaderWriter/ELF/PPC/PPCTargetHandler.h @@ -18,35 +18,49 @@ namespace elf { typedef llvm::object::ELFType<llvm::support::big, 2, false> PPCELFType; class PPCLinkingContext; +template <class ELFT> class PPCTargetLayout : public TargetLayout<ELFT> { +public: + PPCTargetLayout(PPCLinkingContext &context) : TargetLayout<ELFT>(context) {} +}; + class PPCTargetRelocationHandler LLVM_FINAL : public TargetRelocationHandler<PPCELFType> { public: - PPCTargetRelocationHandler(const PPCLinkingContext &context) {} + PPCTargetRelocationHandler(PPCLinkingContext &context, + PPCTargetLayout<PPCELFType> &layout) + : _ppcContext(context), _ppcTargetLayout(layout) {} virtual error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &, const lld::AtomLayout &, const Reference &) const; +protected: + PPCLinkingContext &_ppcContext; + PPCTargetLayout<PPCELFType> &_ppcTargetLayout; }; class PPCTargetHandler LLVM_FINAL : public DefaultTargetHandler<PPCELFType> { public: - PPCTargetHandler(PPCLinkingContext &targetInfo); + PPCTargetHandler(PPCLinkingContext &context); - virtual void registerRelocationNames(Registry ®istry); + virtual PPCTargetLayout<PPCELFType> &getTargetLayout() { + return *(_ppcTargetLayout.get()); + } - virtual TargetLayout<PPCELFType> &targetLayout() { return _targetLayout; } + virtual void registerRelocationNames(Registry ®istry); virtual const PPCTargetRelocationHandler &getRelocationHandler() const { - return _relocationHandler; + return *(_ppcRelocationHandler.get()); } + virtual std::unique_ptr<Writer> getWriter(); + private: static const Registry::KindStrings kindStrings[]; - - PPCTargetRelocationHandler _relocationHandler; - TargetLayout<PPCELFType> _targetLayout; + PPCLinkingContext &_ppcLinkingContext; + std::unique_ptr<PPCTargetLayout<PPCELFType>> _ppcTargetLayout; + std::unique_ptr<PPCTargetRelocationHandler> _ppcRelocationHandler; }; } // end namespace elf } // end namespace lld diff --git a/lld/lib/ReaderWriter/ELF/SectionChunks.h b/lld/lib/ReaderWriter/ELF/SectionChunks.h index dc3e4bb6275..f6ac670ae32 100644 --- a/lld/lib/ReaderWriter/ELF/SectionChunks.h +++ b/lld/lib/ReaderWriter/ELF/SectionChunks.h @@ -234,7 +234,8 @@ public: range<atom_iter> atoms() { return _atoms; } - virtual void write(ELFWriter *writer, llvm::FileOutputBuffer &buffer); + virtual void write(ELFWriter *writer, TargetLayout<ELFT> &layout, + llvm::FileOutputBuffer &buffer); static bool classof(const Chunk<ELFT> *c) { return c->kind() == Chunk<ELFT>::Kind::AtomSection; @@ -359,7 +360,7 @@ template <class ELFT> StringRef Section<ELFT>::segmentKindToStr() const { /// \brief Write the section and the atom contents to the buffer template <class ELFT> -void AtomSection<ELFT>::write(ELFWriter *writer, +void AtomSection<ELFT>::write(ELFWriter *writer, TargetLayout<ELFT> &layout, llvm::FileOutputBuffer &buffer) { uint8_t *chunkBuffer = buffer.getBufferStart(); parallel_for_each(_atoms.begin(), _atoms.end(), [&](lld::AtomLayout * ai) { @@ -524,7 +525,8 @@ public: uint64_t addString(StringRef symname); - virtual void write(ELFWriter *writer, llvm::FileOutputBuffer &buffer); + virtual void write(ELFWriter *writer, TargetLayout<ELFT> &layout, + llvm::FileOutputBuffer &buffer); inline void setNumEntries(int64_t numEntries) { _stringMap.resize(numEntries); @@ -583,7 +585,7 @@ template <class ELFT> uint64_t StringTable<ELFT>::addString(StringRef symname) { } template <class ELFT> -void StringTable<ELFT>::write(ELFWriter *writer, +void StringTable<ELFT>::write(ELFWriter *writer, TargetLayout<ELFT> &, llvm::FileOutputBuffer &buffer) { uint8_t *chunkBuffer = buffer.getBufferStart(); uint8_t *dest = chunkBuffer + this->fileOffset(); @@ -649,7 +651,8 @@ public: virtual void finalize(bool sort = true); - virtual void write(ELFWriter *writer, llvm::FileOutputBuffer &buffer); + virtual void write(ELFWriter *writer, TargetLayout<ELFT> &layout, + llvm::FileOutputBuffer &buffer); void setStringSection(StringTable<ELFT> *s) { _stringSection = s; } @@ -842,7 +845,7 @@ template <class ELFT> void SymbolTable<ELFT>::finalize(bool sort) { } template <class ELFT> -void SymbolTable<ELFT>::write(ELFWriter *writer, +void SymbolTable<ELFT>::write(ELFWriter *writer, TargetLayout<ELFT> &, llvm::FileOutputBuffer &buffer) { uint8_t *chunkBuffer = buffer.getBufferStart(); uint8_t *dest = chunkBuffer + this->fileOffset(); @@ -856,9 +859,10 @@ template <class ELFT> class HashSection; template <class ELFT> class DynamicSymbolTable : public SymbolTable<ELFT> { public: - DynamicSymbolTable(const ELFLinkingContext &context, const char *str, - int32_t order) - : SymbolTable<ELFT>(context, str, order), _hashTable(nullptr) { + DynamicSymbolTable(const ELFLinkingContext &context, + TargetLayout<ELFT> &layout, const char *str, int32_t order) + : SymbolTable<ELFT>(context, str, order), _hashTable(nullptr), + _layout(layout) { this->_type = SHT_DYNSYM; this->_flags = SHF_ALLOC; this->_msize = this->_fsize; @@ -894,8 +898,9 @@ public: SymbolTable<ELFT>::finalize(false); } -private: +protected: HashSection<ELFT> *_hashTable; + TargetLayout<ELFT> &_layout; }; template <class ELFT> class RelocationTable : public Section<ELFT> { @@ -951,8 +956,10 @@ public: this->_parent->setLink(this->_link); } - virtual void write(ELFWriter *writer, llvm::FileOutputBuffer &buffer) { - uint8_t *dest = buffer.getBufferStart() + this->fileOffset(); + virtual void write(ELFWriter *writer, TargetLayout<ELFT> &layout, + llvm::FileOutputBuffer &buffer) { + uint8_t *chunkBuffer = buffer.getBufferStart(); + uint8_t *dest = chunkBuffer + this->fileOffset(); for (const auto &rel : _relocs) { if (this->_context.isRelaOutputFormat()) writeRela(writer, *reinterpret_cast<Elf_Rela *>(dest), *rel.first, @@ -1007,8 +1014,9 @@ public: typedef llvm::object::Elf_Dyn_Impl<ELFT> Elf_Dyn; typedef std::vector<Elf_Dyn> EntriesT; - DynamicTable(const ELFLinkingContext &context, StringRef str, int32_t order) - : Section<ELFT>(context, str) { + DynamicTable(const ELFLinkingContext &context, TargetLayout<ELFT> &layout, + StringRef str, int32_t order) + : Section<ELFT>(context, str), _layout(layout) { this->setOrder(order); this->_entSize = sizeof(Elf_Dyn); this->_align2 = llvm::alignOf<Elf_Dyn>(); @@ -1017,7 +1025,6 @@ public: this->_msize = sizeof(Elf_Dyn); this->_type = SHT_DYNAMIC; this->_flags = SHF_ALLOC; - _layout = &context.getTargetHandler<ELFT>().targetLayout(); } range<typename EntriesT::iterator> entries() { return _entries; } @@ -1030,7 +1037,8 @@ public: return _entries.size() - 1; } - void write(ELFWriter *writer, llvm::FileOutputBuffer &buffer) { + void write(ELFWriter *writer, TargetLayout<ELFT> &layout, + llvm::FileOutputBuffer &buffer) { uint8_t *chunkBuffer = buffer.getBufferStart(); uint8_t *dest = chunkBuffer + this->fileOffset(); // Add the null entry. @@ -1061,7 +1069,7 @@ public: _dt_fini_array = addEntry(dyn); dyn.d_tag = DT_FINI_ARRAYSZ; _dt_fini_arraysz = addEntry(dyn); - if (_layout->hasDynamicRelocationTable()) { + if (_layout.hasDynamicRelocationTable()) { dyn.d_tag = isRela ? DT_RELA : DT_REL; _dt_rela = addEntry(dyn); dyn.d_tag = isRela ? DT_RELASZ : DT_RELSZ; @@ -1069,7 +1077,7 @@ public: dyn.d_tag = isRela ? DT_RELAENT : DT_RELENT; _dt_relaent = addEntry(dyn); } - if (_layout->hasPLTRelocationTable()) { + if (_layout.hasPLTRelocationTable()) { dyn.d_tag = DT_PLTRELSZ; _dt_pltrelsz = addEntry(dyn); dyn.d_tag = DT_PLTGOT; @@ -1111,30 +1119,28 @@ public: _entries[_dt_symtab].d_un.d_val = _dynamicSymbolTable->virtualAddr(); _entries[_dt_strsz].d_un.d_val = dynamicStringTable->memSize(); _entries[_dt_syment].d_un.d_val = _dynamicSymbolTable->getEntSize(); - auto finiArray = _layout->findOutputSection(".fini_array"); + auto finiArray = _layout.findOutputSection(".fini_array"); if (finiArray) { _entries[_dt_fini_array].d_un.d_val = finiArray->virtualAddr(); _entries[_dt_fini_arraysz].d_un.d_val = finiArray->memSize(); } - if (_layout->hasDynamicRelocationTable()) { - auto relaTbl = _layout->getDynamicRelocationTable(); + if (_layout.hasDynamicRelocationTable()) { + auto relaTbl = _layout.getDynamicRelocationTable(); _entries[_dt_rela].d_un.d_val = relaTbl->virtualAddr(); _entries[_dt_relasz].d_un.d_val = relaTbl->memSize(); _entries[_dt_relaent].d_un.d_val = relaTbl->getEntSize(); } - if (_layout->hasPLTRelocationTable()) { - auto relaTbl = _layout->getPLTRelocationTable(); + if (_layout.hasPLTRelocationTable()) { + auto relaTbl = _layout.getPLTRelocationTable(); _entries[_dt_jmprel].d_un.d_val = relaTbl->virtualAddr(); _entries[_dt_pltrelsz].d_un.d_val = relaTbl->memSize(); - auto gotplt = _layout->findOutputSection(".got.plt"); + auto gotplt = _layout.findOutputSection(".got.plt"); _entries[_dt_pltgot].d_un.d_val = gotplt->virtualAddr(); } } protected: EntriesT _entries; - -private: std::size_t _dt_hash; std::size_t _dt_strtab; std::size_t _dt_symtab; @@ -1149,7 +1155,7 @@ private: std::size_t _dt_jmprel; std::size_t _dt_fini_array; std::size_t _dt_fini_arraysz; - TargetLayout<ELFT> *_layout; + TargetLayout<ELFT> &_layout; DynamicSymbolTable<ELFT> *_dynamicSymbolTable; HashSection<ELFT> *_hashTable; }; @@ -1168,7 +1174,8 @@ public: this->_flags = SHF_ALLOC; } - void write(ELFWriter *writer, llvm::FileOutputBuffer &buffer) { + void write(ELFWriter *writer, TargetLayout<ELFT> &layout, + llvm::FileOutputBuffer &buffer) { uint8_t *chunkBuffer = buffer.getBufferStart(); uint8_t *dest = chunkBuffer + this->fileOffset(); std::memcpy(dest, _interp.data(), _interp.size()); @@ -1280,7 +1287,8 @@ public: this->_parent->setLink(this->_link); } - virtual void write(ELFWriter *writer, llvm::FileOutputBuffer &buffer) { + virtual void write(ELFWriter *writer, TargetLayout<ELFT> &layout, + llvm::FileOutputBuffer &buffer) { uint8_t *chunkBuffer = buffer.getBufferStart(); uint8_t *dest = chunkBuffer + this->fileOffset(); uint32_t bucketChainCounts[2]; @@ -1311,8 +1319,9 @@ private: template <class ELFT> class EHFrameHeader : public Section<ELFT> { public: - EHFrameHeader(const ELFLinkingContext &context, StringRef name, int32_t order) - : Section<ELFT>(context, name) { + EHFrameHeader(const ELFLinkingContext &context, StringRef name, + TargetLayout<ELFT> &layout, int32_t order) + : Section<ELFT>(context, name), _layout(layout) { this->setOrder(order); this->_entSize = 0; this->_type = SHT_PROGBITS; @@ -1332,13 +1341,11 @@ public: } virtual void finalize() LLVM_OVERRIDE { - MergedSections<ELFT> *s = this->_context.template getTargetHandler<ELFT>() - .targetLayout() - .findOutputSection(".eh_frame"); + MergedSections<ELFT> *s = _layout.findOutputSection(".eh_frame"); _ehFrameAddr = s ? s->virtualAddr() : 0; } - virtual void write(ELFWriter *writer, + virtual void write(ELFWriter *writer, TargetLayout<ELFT> &layout, llvm::FileOutputBuffer &buffer) LLVM_OVERRIDE { uint8_t *chunkBuffer = buffer.getBufferStart(); uint8_t *dest = chunkBuffer + this->fileOffset(); @@ -1353,6 +1360,7 @@ public: private: uint64_t _ehFrameAddr; + TargetLayout<ELFT> &_layout; }; } // end namespace elf } // end namespace lld diff --git a/lld/lib/ReaderWriter/ELF/SegmentChunks.h b/lld/lib/ReaderWriter/ELF/SegmentChunks.h index 3b85161109b..8e47499128b 100644 --- a/lld/lib/ReaderWriter/ELF/SegmentChunks.h +++ b/lld/lib/ReaderWriter/ELF/SegmentChunks.h @@ -159,7 +159,8 @@ public: void assignVirtualAddress(uint64_t &addr); // Write the Segment - void write(ELFWriter *writer, llvm::FileOutputBuffer &buffer); + void write(ELFWriter *writer, TargetLayout<ELFT> &layout, + llvm::FileOutputBuffer &buffer); int64_t flags() const; @@ -582,10 +583,11 @@ template <class ELFT> void Segment<ELFT>::assignVirtualAddress(uint64_t &addr) { // Write the Segment template <class ELFT> -void Segment<ELFT>::write(ELFWriter *writer, llvm::FileOutputBuffer &buffer) { +void Segment<ELFT>::write(ELFWriter *writer, TargetLayout<ELFT> &layout, + llvm::FileOutputBuffer &buffer) { for (auto slice : slices()) for (auto section : slice->sections()) - section->write(writer, buffer); + section->write(writer, layout, buffer); } template<class ELFT> diff --git a/lld/lib/ReaderWriter/ELF/TargetHandler.h b/lld/lib/ReaderWriter/ELF/TargetHandler.h index 1dada951cb7..8f8e1f05257 100644 --- a/lld/lib/ReaderWriter/ELF/TargetHandler.h +++ b/lld/lib/ReaderWriter/ELF/TargetHandler.h @@ -42,63 +42,38 @@ template <class ELFT> class TargetLayout; template <class ELFT> class TargetRelocationHandler { public: - virtual error_code - applyRelocation(ELFWriter &, llvm::FileOutputBuffer &, - const lld::AtomLayout &, const Reference &) const = 0; + virtual error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &, + const lld::AtomLayout &, + const Reference &) const = 0; virtual ~TargetRelocationHandler() {} }; -/// \brief An interface to override functions that are provided by the -/// the default ELF Layout +/// \brief TargetHandler contains all the information responsible to handle a +/// a particular target on ELF. A target might wish to override implementation +/// of creating atoms and how the atoms are written to the output file. template <class ELFT> class TargetHandler : public TargetHandlerBase { public: + /// Constructor TargetHandler(ELFLinkingContext &targetInfo) : _context(targetInfo) {} - /// If the target overrides ELF header information, this API would - /// return true, so that the target can set all fields specific to - /// that target - virtual bool doesOverrideELFHeader() = 0; - - /// Set the ELF Header information - virtual void setELFHeader(ELFHeader<ELFT> *elfHeader) = 0; - - /// TargetLayout - virtual TargetLayout<ELFT> &targetLayout() = 0; + /// The layout determined completely by the Target. + virtual TargetLayout<ELFT> &getTargetLayout() = 0; + /// Determine how relocations need to be applied. virtual const TargetRelocationHandler<ELFT> &getRelocationHandler() const = 0; - /// Create a set of Default target sections that a target might needj - virtual void createDefaultSections() = 0; - - /// \brief Add a section to the current Layout - virtual void addSection(Section<ELFT> *section) = 0; - - /// \brief add new symbol file - virtual bool createImplicitFiles(std::vector<std::unique_ptr<File> > &) = 0; - - /// \brief Finalize the symbol values - virtual void finalizeSymbolValues() = 0; - - /// \brief allocate Commons, some architectures may move small common - /// symbols over to small data, this would also be used - virtual void allocateCommons() = 0; - - /// \brief create dynamic table - virtual LLD_UNIQUE_BUMP_PTR(DynamicTable<ELFT>) createDynamicTable() = 0; - - /// \brief create dynamic symbol table - virtual LLD_UNIQUE_BUMP_PTR(DynamicSymbolTable<ELFT>) - createDynamicSymbolTable() = 0; - + /// How does the target deal with reading input files. virtual std::unique_ptr<Reader> getObjReader(bool) = 0; + /// How does the target deal with reading dynamic libraries. virtual std::unique_ptr<Reader> getDSOReader(bool) = 0; + /// How does the target deal with writing ELF output. virtual std::unique_ptr<Writer> getWriter() = 0; -protected: +private: ELFLinkingContext &_context; }; } // end namespace elf diff --git a/lld/lib/ReaderWriter/ELF/X86/X86TargetHandler.cpp b/lld/lib/ReaderWriter/ELF/X86/X86TargetHandler.cpp index ba66416ae28..367b4d8073d 100644 --- a/lld/lib/ReaderWriter/ELF/X86/X86TargetHandler.cpp +++ b/lld/lib/ReaderWriter/ELF/X86/X86TargetHandler.cpp @@ -31,6 +31,21 @@ static int relocPC32(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) { return 0; } +std::unique_ptr<Writer> X86TargetHandler::getWriter() { + switch (_x86LinkingContext.getOutputELFType()) { + case llvm::ELF::ET_EXEC: + return std::unique_ptr<Writer>(new elf::ExecutableWriter<X86ELFType>( + _x86LinkingContext, *_x86TargetLayout.get())); + case llvm::ELF::ET_DYN: + return std::unique_ptr<Writer>(new elf::DynamicLibraryWriter<X86ELFType>( + _x86LinkingContext, *_x86TargetLayout.get())); + case llvm::ELF::ET_REL: + llvm_unreachable("TODO: support -r mode"); + default: + llvm_unreachable("unsupported output type"); + } +} + const Registry::KindStrings X86TargetHandler::kindStrings[] = { LLD_KIND_STRING_ENTRY(R_386_NONE), LLD_KIND_STRING_ENTRY(R_386_32), @@ -111,6 +126,8 @@ error_code X86TargetRelocationHandler::applyRelocation( return error_code::success(); } -X86TargetHandler::X86TargetHandler(X86LinkingContext &targetInfo) - : DefaultTargetHandler(targetInfo), _relocationHandler(targetInfo), - _targetLayout(targetInfo) {} +X86TargetHandler::X86TargetHandler(X86LinkingContext &context) + : DefaultTargetHandler(context), _x86LinkingContext(context), + _x86TargetLayout(new X86TargetLayout<X86ELFType>(context)), + _x86RelocationHandler( + new X86TargetRelocationHandler(context, *_x86TargetLayout.get())) {} diff --git a/lld/lib/ReaderWriter/ELF/X86/X86TargetHandler.h b/lld/lib/ReaderWriter/ELF/X86/X86TargetHandler.h index 86fbeacf8e9..7918c190680 100644 --- a/lld/lib/ReaderWriter/ELF/X86/X86TargetHandler.h +++ b/lld/lib/ReaderWriter/ELF/X86/X86TargetHandler.h @@ -21,16 +21,27 @@ namespace elf { typedef llvm::object::ELFType<llvm::support::little, 2, false> X86ELFType; class X86LinkingContext; +template <class ELFT> class X86TargetLayout : public TargetLayout<ELFT> { +public: + X86TargetLayout(X86LinkingContext &context) : TargetLayout<ELFT>(context) {} +}; + class X86TargetRelocationHandler LLVM_FINAL : public TargetRelocationHandler<X86ELFType> { public: - X86TargetRelocationHandler(const X86LinkingContext &context) {} + X86TargetRelocationHandler(X86LinkingContext &context, + X86TargetLayout<X86ELFType> &layout) + : _x86Context(context), _x86TargetLayout(layout) {} virtual error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &, const lld::AtomLayout &, const Reference &) const; static const Registry::KindStrings kindStrings[]; + +protected: + X86LinkingContext &_x86Context; + X86TargetLayout<X86ELFType> &_x86TargetLayout; }; class X86TargetHandler LLVM_FINAL @@ -38,19 +49,23 @@ class X86TargetHandler LLVM_FINAL public: X86TargetHandler(X86LinkingContext &context); - virtual void registerRelocationNames(Registry ®istry); + virtual X86TargetLayout<X86ELFType> &getTargetLayout() { + return *(_x86TargetLayout.get()); + } - virtual TargetLayout<X86ELFType> &targetLayout() { return _targetLayout; } + virtual void registerRelocationNames(Registry ®istry); virtual const X86TargetRelocationHandler &getRelocationHandler() const { - return _relocationHandler; + return *(_x86RelocationHandler.get()); } -private: - static const Registry::KindStrings kindStrings[]; + virtual std::unique_ptr<Writer> getWriter(); - X86TargetRelocationHandler _relocationHandler; - TargetLayout<X86ELFType> _targetLayout; +protected: + static const Registry::KindStrings kindStrings[]; + X86LinkingContext &_x86LinkingContext; + std::unique_ptr<X86TargetLayout<X86ELFType>> _x86TargetLayout; + std::unique_ptr<X86TargetRelocationHandler> _x86RelocationHandler; }; } // end namespace elf } // end namespace lld diff --git a/lld/lib/ReaderWriter/ELF/X86_64/X86_64DynamicLibraryWriter.h b/lld/lib/ReaderWriter/ELF/X86_64/X86_64DynamicLibraryWriter.h new file mode 100644 index 00000000000..aaaa730c6b0 --- /dev/null +++ b/lld/lib/ReaderWriter/ELF/X86_64/X86_64DynamicLibraryWriter.h @@ -0,0 +1,70 @@ +//===- lib/ReaderWriter/ELF/X86/X86_64DynamicLibraryWriter.h +//-----------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#ifndef X86_64_DYNAMIC_LIBRARY_WRITER_H +#define X86_64_DYNAMIC_LIBRARY_WRITER_H + +#include "DynamicLibraryWriter.h" +#include "X86_64LinkingContext.h" + +namespace lld { +namespace elf { + +template <class ELFT> +class X86_64DynamicLibraryWriter : public DynamicLibraryWriter<ELFT> { +public: + X86_64DynamicLibraryWriter(X86_64LinkingContext &context, + X86_64TargetLayout<ELFT> &layout); + +protected: + // Add any runtime files and their atoms to the output + virtual bool createImplicitFiles(std::vector<std::unique_ptr<File>> &); + + virtual void finalizeDefaultAtomValues() { + return DynamicLibraryWriter<ELFT>::finalizeDefaultAtomValues(); + } + + virtual void addDefaultAtoms() { + return DynamicLibraryWriter<ELFT>::addDefaultAtoms(); + } + +private: + class GOTFile : public SimpleFile { + public: + GOTFile(const ELFLinkingContext &eti) : SimpleFile("GOTFile") {} + llvm::BumpPtrAllocator _alloc; + }; + + std::unique_ptr<GOTFile> _gotFile; + X86_64LinkingContext &_context; + X86_64TargetLayout<ELFT> &_x86_64Layout; +}; + +template <class ELFT> +X86_64DynamicLibraryWriter<ELFT>::X86_64DynamicLibraryWriter( + X86_64LinkingContext &context, X86_64TargetLayout<ELFT> &layout) + : DynamicLibraryWriter<ELFT>(context, layout), + _gotFile(new GOTFile(context)), _context(context), _x86_64Layout(layout) { +} + +template <class ELFT> +bool X86_64DynamicLibraryWriter<ELFT>::createImplicitFiles( + std::vector<std::unique_ptr<File>> &result) { + DynamicLibraryWriter<ELFT>::createImplicitFiles(result); + _gotFile->addAtom(*new (_gotFile->_alloc) GLOBAL_OFFSET_TABLEAtom(*_gotFile)); + _gotFile->addAtom(*new (_gotFile->_alloc) TLSGETADDRAtom(*_gotFile)); + _gotFile->addAtom(*new (_gotFile->_alloc) DYNAMICAtom(*_gotFile)); + result.push_back(std::move(_gotFile)); + return true; +} + +} // namespace elf +} // namespace lld + +#endif diff --git a/lld/lib/ReaderWriter/ELF/X86_64/X86_64ExecutableWriter.h b/lld/lib/ReaderWriter/ELF/X86_64/X86_64ExecutableWriter.h new file mode 100644 index 00000000000..aec677292a1 --- /dev/null +++ b/lld/lib/ReaderWriter/ELF/X86_64/X86_64ExecutableWriter.h @@ -0,0 +1,70 @@ +//===- lib/ReaderWriter/ELF/X86/X86_64ExecutableWriter.h +//-----------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#ifndef X86_64_EXECUTABLE_WRITER_H +#define X86_64_EXECUTABLE_WRITER_H + +#include "ExecutableWriter.h" +#include "X86_64LinkingContext.h" + +namespace lld { +namespace elf { + +template <class ELFT> +class X86_64ExecutableWriter : public ExecutableWriter<ELFT> { +public: + X86_64ExecutableWriter(X86_64LinkingContext &context, + X86_64TargetLayout<ELFT> &layout); + +protected: + // Add any runtime files and their atoms to the output + virtual bool createImplicitFiles(std::vector<std::unique_ptr<File>> &); + + virtual void finalizeDefaultAtomValues() { + return ExecutableWriter<ELFT>::finalizeDefaultAtomValues(); + } + + virtual void addDefaultAtoms() { + return ExecutableWriter<ELFT>::addDefaultAtoms(); + } + +private: + class GOTFile : public SimpleFile { + public: + GOTFile(const ELFLinkingContext &eti) : SimpleFile("GOTFile") {} + llvm::BumpPtrAllocator _alloc; + }; + + std::unique_ptr<GOTFile> _gotFile; + X86_64LinkingContext &_context; + X86_64TargetLayout<ELFT> &_x86_64Layout; +}; + +template <class ELFT> +X86_64ExecutableWriter<ELFT>::X86_64ExecutableWriter( + X86_64LinkingContext &context, X86_64TargetLayout<ELFT> &layout) + : ExecutableWriter<ELFT>(context, layout), _gotFile(new GOTFile(context)), + _context(context), _x86_64Layout(layout) {} + +template <class ELFT> +bool X86_64ExecutableWriter<ELFT>::createImplicitFiles( + std::vector<std::unique_ptr<File>> &result) { + ExecutableWriter<ELFT>::createImplicitFiles(result); + _gotFile->addAtom(*new (_gotFile->_alloc) GLOBAL_OFFSET_TABLEAtom(*_gotFile)); + _gotFile->addAtom(*new (_gotFile->_alloc) TLSGETADDRAtom(*_gotFile)); + if (_context.isDynamic()) + _gotFile->addAtom(*new (_gotFile->_alloc) DYNAMICAtom(*_gotFile)); + result.push_back(std::move(_gotFile)); + return true; +} + +} // namespace elf +} // namespace lld + +#endif diff --git a/lld/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp b/lld/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp index bab665c8d00..750b9d1bd73 100644 --- a/lld/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp +++ b/lld/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp @@ -90,8 +90,7 @@ error_code X86_64TargetRelocationHandler::applyRelocation( case R_X86_64_TPOFF64: case R_X86_64_DTPOFF32: case R_X86_64_TPOFF32: { - _tlsSize = - _context.getTargetHandler<X86_64ELFType>().targetLayout().getTLSSize(); + _tlsSize = _x86_64Layout.getTLSSize(); if (ref.kindValue() == R_X86_64_TPOFF32 || ref.kindValue() == R_X86_64_DTPOFF32) { int32_t result = (int32_t)(targetVAddress - _tlsSize); @@ -115,8 +114,8 @@ error_code X86_64TargetRelocationHandler::applyRelocation( for (const Reference *r : *target) { if (r->kindValue() == R_X86_64_JUMP_SLOT) { uint32_t index; - if (!_context.getTargetHandler<X86_64ELFType>().targetLayout() - .getPLTRelocationTable()->getRelocationIndex(*r, index)) + if (!_x86_64Layout.getPLTRelocationTable()->getRelocationIndex(*r, + index)) llvm_unreachable("Relocation doesn't exist"); reloc32(location, 0, index, 0); break; diff --git a/lld/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.h b/lld/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.h index 5a1198a3590..d11463f4d0e 100644 --- a/lld/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.h +++ b/lld/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.h @@ -8,8 +8,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLD_READER_WRITER_ELF_X86_64_X86_64_RELOCATION_HANDLER_H -#define LLD_READER_WRITER_ELF_X86_64_X86_64_RELOCATION_HANDLER_H +#ifndef X86_64_RELOCATION_HANDLER_H +#define X86_64_RELOCATION_HANDLER_H #include "X86_64TargetHandler.h" @@ -18,11 +18,14 @@ namespace elf { typedef llvm::object::ELFType<llvm::support::little, 2, true> X86_64ELFType; class X86_64LinkingContext; +template <class ELFT> class X86_64TargetLayout; + class X86_64TargetRelocationHandler LLVM_FINAL : public TargetRelocationHandler<X86_64ELFType> { public: - X86_64TargetRelocationHandler(const X86_64LinkingContext &context) - : _tlsSize(0), _context(context) {} + X86_64TargetRelocationHandler(const X86_64LinkingContext &context, + X86_64TargetLayout<X86_64ELFType> &layout) + : _tlsSize(0), _context(context), _x86_64Layout(layout) {} virtual error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &, const lld::AtomLayout &, @@ -35,10 +38,11 @@ public: private: // Cached size of the TLS segment. mutable uint64_t _tlsSize; - const X86_64LinkingContext &_context; + const X86_64LinkingContext &_context LLVM_ATTRIBUTE_UNUSED; + X86_64TargetLayout<X86_64ELFType> &_x86_64Layout; }; } // end namespace elf } // end namespace lld -#endif +#endif // X86_64_RELOCATION_HANDLER_H diff --git a/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp b/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp index a553b2dd22f..171958f1035 100644 --- a/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp +++ b/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp @@ -8,6 +8,8 @@ //===----------------------------------------------------------------------===// #include "Atoms.h" +#include "X86_64ExecutableWriter.h" +#include "X86_64DynamicLibraryWriter.h" #include "X86_64TargetHandler.h" #include "X86_64LinkingContext.h" @@ -15,24 +17,32 @@ using namespace lld; using namespace elf; X86_64TargetHandler::X86_64TargetHandler(X86_64LinkingContext &context) - : DefaultTargetHandler(context), _gotFile(new GOTFile(context)), - _relocationHandler(context), _targetLayout(context) {} - -bool X86_64TargetHandler::createImplicitFiles( - std::vector<std::unique_ptr<File> > &result) { - _gotFile->addAtom(*new (_gotFile->_alloc) GLOBAL_OFFSET_TABLEAtom(*_gotFile)); - _gotFile->addAtom(*new (_gotFile->_alloc) TLSGETADDRAtom(*_gotFile)); - if (_context.isDynamic()) - _gotFile->addAtom(*new (_gotFile->_alloc) DYNAMICAtom(*_gotFile)); - result.push_back(std::move(_gotFile)); - return true; -} + : DefaultTargetHandler(context), _context(context), + _x86_64TargetLayout(new X86_64TargetLayout<X86_64ELFType>(context)), + _x86_64RelocationHandler(new X86_64TargetRelocationHandler( + context, *_x86_64TargetLayout.get())) {} void X86_64TargetHandler::registerRelocationNames(Registry ®istry) { registry.addKindTable(Reference::KindNamespace::ELF, Reference::KindArch::x86_64, kindStrings); } +std::unique_ptr<Writer> X86_64TargetHandler::getWriter() { + switch (this->_context.getOutputELFType()) { + case llvm::ELF::ET_EXEC: + return std::unique_ptr<Writer>(new X86_64ExecutableWriter<X86_64ELFType>( + _context, *_x86_64TargetLayout.get())); + case llvm::ELF::ET_DYN: + return std::unique_ptr<Writer>( + new X86_64DynamicLibraryWriter<X86_64ELFType>( + _context, *_x86_64TargetLayout.get())); + case llvm::ELF::ET_REL: + llvm_unreachable("TODO: support -r mode"); + default: + llvm_unreachable("unsupported output type"); + } +} + const Registry::KindStrings X86_64TargetHandler::kindStrings[] = { LLD_KIND_STRING_ENTRY(R_X86_64_NONE), LLD_KIND_STRING_ENTRY(R_X86_64_64), diff --git a/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h b/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h index aea7e851a0e..c3c3616ad63 100644 --- a/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h +++ b/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h @@ -22,35 +22,36 @@ namespace elf { typedef llvm::object::ELFType<llvm::support::little, 2, true> X86_64ELFType; class X86_64LinkingContext; +template <class ELFT> class X86_64TargetLayout : public TargetLayout<ELFT> { +public: + X86_64TargetLayout(X86_64LinkingContext &context) + : TargetLayout<ELFT>(context) {} +}; + class X86_64TargetHandler LLVM_FINAL : public DefaultTargetHandler<X86_64ELFType> { public: - X86_64TargetHandler(X86_64LinkingContext &targetInfo); - - virtual void registerRelocationNames(Registry ®istry); + X86_64TargetHandler(X86_64LinkingContext &context); - virtual TargetLayout<X86_64ELFType> &targetLayout() { - return _targetLayout; + virtual X86_64TargetLayout<X86_64ELFType> &getTargetLayout() { + return *(_x86_64TargetLayout.get()); } + virtual void registerRelocationNames(Registry ®istry); + virtual const X86_64TargetRelocationHandler &getRelocationHandler() const { - return _relocationHandler; + return *(_x86_64RelocationHandler.get()); } - virtual bool createImplicitFiles(std::vector<std::unique_ptr<File> > &); + virtual std::unique_ptr<Writer> getWriter(); private: - class GOTFile : public SimpleFile { - public: - GOTFile(const ELFLinkingContext &eti) : SimpleFile("GOTFile") {} - llvm::BumpPtrAllocator _alloc; - }; - static const Registry::KindStrings kindStrings[]; - std::unique_ptr<GOTFile> _gotFile; - X86_64TargetRelocationHandler _relocationHandler; - TargetLayout<X86_64ELFType> _targetLayout; + X86_64LinkingContext &_context; + std::unique_ptr<X86_64TargetLayout<X86_64ELFType>> _x86_64TargetLayout; + std::unique_ptr<X86_64TargetRelocationHandler> _x86_64RelocationHandler; }; + } // end namespace elf } // end namespace lld diff --git a/lld/test/elf/Hexagon/dynlib-syms.test b/lld/test/elf/Hexagon/dynlib-syms.test index fbfc550a459..5ac714bff1d 100644 --- a/lld/test/elf/Hexagon/dynlib-syms.test +++ b/lld/test/elf/Hexagon/dynlib-syms.test @@ -5,4 +5,3 @@ RUN: FileCheck -check-prefix=CHECKSYMS %s < %t1 CHECKSYMS: 0000028c A _DYNAMIC CHECKSYMS: 00001008 A _GLOBAL_OFFSET_TABLE_ -CHECKSYMS: 00002000 A _SDA_BASE_ |

