diff options
| author | Denis Protivensky <dprotivensky@accesssoftek.com> | 2015-04-24 08:53:02 +0000 |
|---|---|---|
| committer | Denis Protivensky <dprotivensky@accesssoftek.com> | 2015-04-24 08:53:02 +0000 |
| commit | c3431bf67be0baabb8756facd091728ad853772f (patch) | |
| tree | cf1c69643dd61a77135e676c62044bcb9a15cb76 /lld/lib/ReaderWriter/ELF/ARM | |
| parent | 53e047de9ed62854cbd887768cd2bac1bb8a531a (diff) | |
| download | bcm5719-llvm-c3431bf67be0baabb8756facd091728ad853772f.tar.gz bcm5719-llvm-c3431bf67be0baabb8756facd091728ad853772f.zip | |
[ARM] Implement R_ARM_COPY relocation
This adds support of copying objects from shared libraries.
llvm-svn: 235705
Diffstat (limited to 'lld/lib/ReaderWriter/ELF/ARM')
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.h | 8 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp | 35 |
2 files changed, 41 insertions, 2 deletions
diff --git a/lld/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.h b/lld/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.h index 883180798c3..0c33e881fdd 100644 --- a/lld/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.h +++ b/lld/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.h @@ -39,12 +39,20 @@ public: assert(r.kindArch() == Reference::KindArch::ARM); switch (r.kindValue()) { case llvm::ELF::R_ARM_TLS_TPOFF32: + case llvm::ELF::R_ARM_COPY: return true; default: return false; } } + bool isCopyRelocation(const Reference &r) const override { + if (r.kindNamespace() != Reference::KindNamespace::ELF) + return false; + assert(r.kindArch() == Reference::KindArch::ARM); + return r.kindValue() == llvm::ELF::R_ARM_COPY; + } + bool isPLTRelocation(const Reference &r) const override { if (r.kindNamespace() != Reference::KindNamespace::ELF) return false; diff --git a/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp b/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp index 6badc5e0779..e0d1582d8af 100644 --- a/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp +++ b/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp @@ -304,6 +304,14 @@ public: Alignment alignment() const override { return 4; } }; +/// \brief Atom which represents an object for which a COPY relocation will +/// be generated. +class ARMObjectAtom : public ObjectAtom { +public: + ARMObjectAtom(const File &f) : ObjectAtom(f) {} + Alignment alignment() const override { return 4; } +}; + class ELFPassFile : public SimpleFile { public: ELFPassFile(const ELFLinkingContext &eti) : SimpleFile("ELFPassFile") { @@ -732,6 +740,11 @@ public: got->setOrdinal(ordinal++); mf->addAtom(*got); } + for (auto &objectKV : _objectAtoms) { + auto &obj = objectKV.second; + obj->setOrdinal(ordinal++); + mf->addAtom(*obj); + } for (auto &veneerKV : _veneerAtoms) { auto &veneer = veneerKV.second; auto *m = veneer._mapping; @@ -751,6 +764,9 @@ protected: /// \brief Map Atoms to their GOT entries. llvm::MapVector<const Atom *, GOTAtom *> _gotAtoms; + /// \brief Map Atoms to their Object entries. + llvm::MapVector<const Atom *, ObjectAtom *> _objectAtoms; + /// \brief Map Atoms to their PLT entries depending on the code model. struct PLTWithVeneer { PLTWithVeneer(PLTAtom *p = nullptr, PLTAtom *v = nullptr) @@ -857,11 +873,26 @@ public: return g; } + const ObjectAtom *getObjectEntry(const SharedLibraryAtom *a) { + if (auto obj = _objectAtoms.lookup(a)) + return obj; + + auto oa = new (_file._alloc) ARMObjectAtom(_file); + oa->addReferenceELF_ARM(R_ARM_COPY, 0, oa, 0); + + oa->_name = a->name(); + oa->_size = a->size(); + + _objectAtoms[a] = oa; + return oa; + } + /// \brief Handle ordinary relocation references. std::error_code handlePlain(bool fromThumb, const Reference &ref) { if (auto sla = dyn_cast<SharedLibraryAtom>(ref.target())) { - if (sla->type() == SharedLibraryAtom::Type::Data) { - llvm_unreachable("Handle object entries"); + if (sla->type() == SharedLibraryAtom::Type::Data && + _ctx.getOutputELFType() == llvm::ELF::ET_EXEC) { + const_cast<Reference &>(ref).setTarget(getObjectEntry(sla)); } else if (sla->type() == SharedLibraryAtom::Type::Code) { const_cast<Reference &>(ref).setTarget(getPLTEntry(sla, fromThumb)); } |

