diff options
Diffstat (limited to 'lld/lib/ReaderWriter/ELF/ARM')
-rw-r--r-- | lld/lib/ReaderWriter/ELF/ARM/ARMELFFile.h | 56 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/ELF/ARM/ARMExecutableWriter.h | 11 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/ELF/ARM/ARMSymbolTable.h | 46 |
3 files changed, 113 insertions, 0 deletions
diff --git a/lld/lib/ReaderWriter/ELF/ARM/ARMELFFile.h b/lld/lib/ReaderWriter/ELF/ARM/ARMELFFile.h index bba3bbba9a0..7197cb87c0f 100644 --- a/lld/lib/ReaderWriter/ELF/ARM/ARMELFFile.h +++ b/lld/lib/ReaderWriter/ELF/ARM/ARMELFFile.h @@ -17,6 +17,39 @@ namespace elf { class ARMLinkingContext; +template <class ELFT> class ARMELFDefinedAtom : public ELFDefinedAtom<ELFT> { + typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym; + typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr; + +public: + ARMELFDefinedAtom(const ELFFile<ELFT> &file, StringRef symbolName, + StringRef sectionName, const Elf_Sym *symbol, + const Elf_Shdr *section, ArrayRef<uint8_t> contentData, + unsigned int referenceStart, unsigned int referenceEnd, + std::vector<ELFReference<ELFT> *> &referenceList) + : ELFDefinedAtom<ELFT>(file, symbolName, sectionName, symbol, section, + contentData, referenceStart, referenceEnd, + referenceList) {} + + bool isThumbFunc(const Elf_Sym *symbol) const { + return symbol->getType() == llvm::ELF::STT_FUNC && + (static_cast<uint64_t>(symbol->st_value) & 0x1); + } + + /// Correct st_value for symbols addressing Thumb instructions + /// by removing its zero bit. + uint64_t getSymbolValue(const Elf_Sym *symbol) const override { + const auto value = static_cast<uint64_t>(symbol->st_value); + return isThumbFunc(symbol) ? value & ~0x1 : value; + } + + DefinedAtom::CodeModel codeModel() const override { + if (isThumbFunc(this->_symbol)) + return DefinedAtom::codeARMThumb; + return DefinedAtom::codeNA; + } +}; + template <class ELFT> class ARMELFFile : public ELFFile<ELFT> { public: ARMELFFile(std::unique_ptr<MemoryBuffer> mb, bool atomizeStrings) @@ -27,6 +60,29 @@ public: return std::unique_ptr<ARMELFFile<ELFT>>( new ARMELFFile<ELFT>(std::move(mb), atomizeStrings)); } + +private: + typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym; + typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr; + + /// Correct st_value for symbols addressing Thumb instructions + /// by removing its zero bit. + uint64_t getSymbolValue(const Elf_Sym *symbol) const override { + const auto value = static_cast<uint64_t>(symbol->st_value); + return symbol->getType() == llvm::ELF::STT_FUNC ? value & ~0x1 : value; + } + + /// Process the Defined symbol and create an atom for it. + ErrorOr<ELFDefinedAtom<ELFT> *> handleDefinedSymbol(StringRef symName, + StringRef sectionName, + const Elf_Sym *sym, const Elf_Shdr *sectionHdr, + ArrayRef<uint8_t> contentData, + unsigned int referenceStart, unsigned int referenceEnd, + std::vector<ELFReference<ELFT> *> &referenceList) override { + return new (this->_readerStorage) ARMELFDefinedAtom<ELFT>( + *this, symName, sectionName, sym, sectionHdr, contentData, + referenceStart, referenceEnd, referenceList); + } }; template <class ELFT> class ARMDynamicFile : public DynamicFile<ELFT> { diff --git a/lld/lib/ReaderWriter/ELF/ARM/ARMExecutableWriter.h b/lld/lib/ReaderWriter/ELF/ARM/ARMExecutableWriter.h index b45cfd25f0c..0c1ff84aae7 100644 --- a/lld/lib/ReaderWriter/ELF/ARM/ARMExecutableWriter.h +++ b/lld/lib/ReaderWriter/ELF/ARM/ARMExecutableWriter.h @@ -12,6 +12,7 @@ #include "ExecutableWriter.h" #include "ARMLinkingContext.h" #include "ARMTargetHandler.h" +#include "ARMSymbolTable.h" namespace lld { namespace elf { @@ -35,6 +36,9 @@ protected: ExecutableWriter<ELFT>::addDefaultAtoms(); } + /// \brief Create symbol table. + LLD_UNIQUE_BUMP_PTR(SymbolTable<ELFT>) createSymbolTable() override; + private: ARMLinkingContext &_context; ARMTargetLayout<ELFT> &_armLayout; @@ -53,6 +57,13 @@ bool ARMExecutableWriter<ELFT>::createImplicitFiles( return true; } +template <class ELFT> +LLD_UNIQUE_BUMP_PTR(SymbolTable<ELFT>) + ARMExecutableWriter<ELFT>::createSymbolTable() { + return LLD_UNIQUE_BUMP_PTR(SymbolTable<ELFT>)( + new (this->_alloc) ARMSymbolTable<ELFT>(this->_context)); +} + } // namespace elf } // namespace lld diff --git a/lld/lib/ReaderWriter/ELF/ARM/ARMSymbolTable.h b/lld/lib/ReaderWriter/ELF/ARM/ARMSymbolTable.h new file mode 100644 index 00000000000..540a480421a --- /dev/null +++ b/lld/lib/ReaderWriter/ELF/ARM/ARMSymbolTable.h @@ -0,0 +1,46 @@ +//===--------- lib/ReaderWriter/ELF/ARM/ARMSymbolTable.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_ARM_ARM_SYMBOL_TABLE_H +#define LLD_READER_WRITER_ELF_ARM_ARM_SYMBOL_TABLE_H + +namespace lld { +namespace elf { + +/// \brief The SymbolTable class represents the symbol table in a ELF file +template<class ELFT> +class ARMSymbolTable : public SymbolTable<ELFT> { +public: + typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym; + + ARMSymbolTable(const ELFLinkingContext &context); + + void addDefinedAtom(Elf_Sym &sym, const DefinedAtom *da, + int64_t addr) override; +}; + +template <class ELFT> +ARMSymbolTable<ELFT>::ARMSymbolTable(const ELFLinkingContext &context) + : SymbolTable<ELFT>(context, ".symtab", + DefaultLayout<ELFT>::ORDER_SYMBOL_TABLE) {} + +template <class ELFT> +void ARMSymbolTable<ELFT>::addDefinedAtom(Elf_Sym &sym, const DefinedAtom *da, + int64_t addr) { + SymbolTable<ELFT>::addDefinedAtom(sym, da, addr); + + // Set zero bit to distinguish symbols addressing Thumb instructions + if (DefinedAtom::codeARMThumb == da->codeModel()) + sym.st_value = static_cast<int64_t>(sym.st_value) | 0x1; +} + +} // elf +} // lld + +#endif // LLD_READER_WRITER_ELF_ARM_ARM_SYMBOL_TABLE_H |