summaryrefslogtreecommitdiffstats
path: root/lld/lib/ReaderWriter/ELF/ARM
diff options
context:
space:
mode:
Diffstat (limited to 'lld/lib/ReaderWriter/ELF/ARM')
-rw-r--r--lld/lib/ReaderWriter/ELF/ARM/ARMELFFile.h56
-rw-r--r--lld/lib/ReaderWriter/ELF/ARM/ARMExecutableWriter.h11
-rw-r--r--lld/lib/ReaderWriter/ELF/ARM/ARMSymbolTable.h46
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
OpenPOWER on IntegriCloud