summaryrefslogtreecommitdiffstats
path: root/lld/lib/ReaderWriter
diff options
context:
space:
mode:
Diffstat (limited to 'lld/lib/ReaderWriter')
-rw-r--r--lld/lib/ReaderWriter/ELF/ARM/ARMELFFile.h50
-rw-r--r--lld/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.cpp17
-rw-r--r--lld/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.h7
-rw-r--r--lld/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp2
-rw-r--r--lld/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp2
-rw-r--r--lld/lib/ReaderWriter/ELF/ARM/ARMSymbolTable.h11
-rw-r--r--lld/lib/ReaderWriter/ELF/Atoms.h6
-rw-r--r--lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp3
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);
}
};
OpenPOWER on IntegriCloud