summaryrefslogtreecommitdiffstats
path: root/lld/lib/ReaderWriter/ELF/ARM
diff options
context:
space:
mode:
authorDenis Protivensky <dprotivensky@accesssoftek.com>2015-04-24 08:53:02 +0000
committerDenis Protivensky <dprotivensky@accesssoftek.com>2015-04-24 08:53:02 +0000
commitc3431bf67be0baabb8756facd091728ad853772f (patch)
treecf1c69643dd61a77135e676c62044bcb9a15cb76 /lld/lib/ReaderWriter/ELF/ARM
parent53e047de9ed62854cbd887768cd2bac1bb8a531a (diff)
downloadbcm5719-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.h8
-rw-r--r--lld/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp35
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));
}
OpenPOWER on IntegriCloud