diff options
Diffstat (limited to 'lld/lib/ReaderWriter')
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/ARM/ARMELFFile.h | 50 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.cpp | 17 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.h | 7 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp | 2 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp | 2 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/ARM/ARMSymbolTable.h | 11 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/Atoms.h | 6 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp | 3 |
8 files changed, 82 insertions, 16 deletions
diff --git a/lld/lib/ReaderWriter/ELF/ARM/ARMELFFile.h b/lld/lib/ReaderWriter/ELF/ARM/ARMELFFile.h index 84af660565f..060dccbd372 100644 --- a/lld/lib/ReaderWriter/ELF/ARM/ARMELFFile.h +++ b/lld/lib/ReaderWriter/ELF/ARM/ARMELFFile.h @@ -17,31 +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; +template <class ELFT, DefinedAtom::CodeModel Model> +class ARMELFMappingAtom : public ELFDefinedAtom<ELFT> { +public: + template<typename... T> + ARMELFMappingAtom(T&&... args) + : ELFDefinedAtom<ELFT>(std::forward<T>(args)...) {} + DefinedAtom::CodeModel codeModel() const override { + return Model; + } +}; + +template <class ELFT> class ARMELFDefinedAtom : public ELFDefinedAtom<ELFT> { public: template<typename... T> ARMELFDefinedAtom(T&&... args) : ELFDefinedAtom<ELFT>(std::forward<T>(args)...) {} - bool isThumbFunc(const Elf_Sym *symbol) const { + bool isThumbFunc() const { + const auto* symbol = this->_symbol; 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; + uint64_t getSymbolValue() const override { + const auto value = static_cast<uint64_t>(this->_symbol->st_value); + return isThumbFunc() ? value & ~0x1 : value; } DefinedAtom::CodeModel codeModel() const override { - if (isThumbFunc(this->_symbol)) - return DefinedAtom::codeARMThumb; - return DefinedAtom::codeNA; + return isThumbFunc() ? DefinedAtom::codeARMThumb : DefinedAtom::codeNA; } }; @@ -74,6 +82,28 @@ private: ArrayRef<uint8_t> contentData, unsigned int referenceStart, unsigned int referenceEnd, std::vector<ELFReference<ELFT> *> &referenceList) override { + if (symName.size() >= 2 && symName[0] == '$') { + switch (symName[1]) { + case 'a': + return new (this->_readerStorage) + ARMELFMappingAtom<ELFT, DefinedAtom::codeARM_a>( + *this, symName, sectionName, sym, sectionHdr, contentData, + referenceStart, referenceEnd, referenceList); + case 'd': + return new (this->_readerStorage) + ARMELFMappingAtom<ELFT, DefinedAtom::codeARM_d>( + *this, symName, sectionName, sym, sectionHdr, contentData, + referenceStart, referenceEnd, referenceList); + case 't': + return new (this->_readerStorage) + ARMELFMappingAtom<ELFT, DefinedAtom::codeARM_t>( + *this, symName, sectionName, sym, sectionHdr, contentData, + referenceStart, referenceEnd, referenceList); + default: + // Fall through and create regular defined atom. + break; + } + } return new (this->_readerStorage) ARMELFDefinedAtom<ELFT>( *this, symName, sectionName, sym, sectionHdr, contentData, referenceStart, referenceEnd, referenceList); diff --git a/lld/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.cpp b/lld/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.cpp index 5f243667426..cc138ddf656 100644 --- a/lld/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.cpp +++ b/lld/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.cpp @@ -32,3 +32,20 @@ void elf::ARMLinkingContext::addPasses(PassManager &pm) { pm.add(std::move(pass)); ELFLinkingContext::addPasses(pm); } + +bool elf::isARMCode(const DefinedAtom *atom) { + return isARMCode(atom->codeModel()); +} + +bool elf::isARMCode(DefinedAtom::CodeModel codeModel) { + return !isThumbCode(codeModel); +} + +bool elf::isThumbCode(const DefinedAtom *atom) { + return isThumbCode(atom->codeModel()); +} + +bool elf::isThumbCode(DefinedAtom::CodeModel codeModel) { + return codeModel == DefinedAtom::codeARMThumb || + codeModel == DefinedAtom::codeARM_t; +} diff --git a/lld/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.h b/lld/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.h index 249b79c4f07..ebb9e1595ad 100644 --- a/lld/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.h +++ b/lld/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.h @@ -30,6 +30,13 @@ public: return _baseAddress; } }; + +// Special methods to check code model of atoms. +bool isARMCode(const DefinedAtom *atom); +bool isARMCode(DefinedAtom::CodeModel codeModel); +bool isThumbCode(const DefinedAtom *atom); +bool isThumbCode(DefinedAtom::CodeModel codeModel); + } // end namespace elf } // end namespace lld diff --git a/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp b/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp index d24fdf0fa41..3032a98f798 100644 --- a/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp +++ b/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp @@ -432,7 +432,7 @@ std::error_code ARMTargetRelocationHandler::applyRelocation( bool addressesThumb = false; if (const auto *definedAtom = dyn_cast<DefinedAtom>(ref.target())) { - addressesThumb = (DefinedAtom::codeARMThumb == definedAtom->codeModel()); + addressesThumb = isThumbCode(definedAtom); } switch (ref.kindValue()) { diff --git a/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp b/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp index 83c21c12eb1..9882df996b3 100644 --- a/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp +++ b/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp @@ -155,7 +155,7 @@ protected: // Target symbol and relocated place should have different // instruction sets in order a veneer to be generated in between. const auto *target = dyn_cast<DefinedAtom>(ref.target()); - if (!target || target->codeModel() == atom.codeModel()) + if (!target || isThumbCode(target) == isThumbCode(&atom)) return std::error_code(); // TODO: For unconditional jump instructions (R_ARM_CALL and R_ARM_THM_CALL) diff --git a/lld/lib/ReaderWriter/ELF/ARM/ARMSymbolTable.h b/lld/lib/ReaderWriter/ELF/ARM/ARMSymbolTable.h index 540a480421a..5c9fec5d550 100644 --- a/lld/lib/ReaderWriter/ELF/ARM/ARMSymbolTable.h +++ b/lld/lib/ReaderWriter/ELF/ARM/ARMSymbolTable.h @@ -35,9 +35,18 @@ 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 + // Set zero bit to distinguish real symbols addressing Thumb instructions. + // Don't care about mapping symbols like $t and others. if (DefinedAtom::codeARMThumb == da->codeModel()) sym.st_value = static_cast<int64_t>(sym.st_value) | 0x1; + + // Mapping symbols should have special values of binding, type and size set. + if ((DefinedAtom::codeARM_a == da->codeModel()) || + (DefinedAtom::codeARM_d == da->codeModel()) || + (DefinedAtom::codeARM_t == da->codeModel())) { + sym.setBindingAndType(llvm::ELF::STB_LOCAL, llvm::ELF::STT_NOTYPE); + sym.st_size = 0; + } } } // elf diff --git a/lld/lib/ReaderWriter/ELF/Atoms.h b/lld/lib/ReaderWriter/ELF/Atoms.h index bf80ebf0a69..df9f38858c8 100644 --- a/lld/lib/ReaderWriter/ELF/Atoms.h +++ b/lld/lib/ReaderWriter/ELF/Atoms.h @@ -293,7 +293,7 @@ public: return 1; // Obtain proper value of st_value field. - const auto symValue = getSymbolValue(_symbol); + const auto symValue = getSymbolValue(); // Unallocated common symbols specify their alignment constraints in // st_value. @@ -429,8 +429,8 @@ public: protected: /// Returns correct st_value for the symbol depending on the architecture. /// For most architectures it's just a regular st_value with no changes. - virtual uint64_t getSymbolValue(const Elf_Sym *symbol) const { - return symbol->st_value; + virtual uint64_t getSymbolValue() const { + return _symbol->st_value; } protected: diff --git a/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp b/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp index 66f5ba810d0..d33c06bad76 100644 --- a/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp +++ b/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp @@ -377,6 +377,9 @@ template <> struct ScalarEnumerationTraits<lld::DefinedAtom::CodeModel> { io.enumCase(value, "mips-micro-pic", lld::DefinedAtom::codeMipsMicroPIC); io.enumCase(value, "mips-16", lld::DefinedAtom::codeMips16); io.enumCase(value, "arm-thumb", lld::DefinedAtom::codeARMThumb); + io.enumCase(value, "arm-a", lld::DefinedAtom::codeARM_a); + io.enumCase(value, "arm-d", lld::DefinedAtom::codeARM_d); + io.enumCase(value, "arm-t", lld::DefinedAtom::codeARM_t); } }; |

