From: Denis Protivensky Date: Fri, 24 Apr 2015 08:53:02 +0000 (+0000) Subject: [ARM] Implement R_ARM_COPY relocation X-Git-Tag: llvmorg-3.7.0-rc1~6078 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c3431bf67be0baabb8756facd091728ad853772f;p=platform%2Fupstream%2Fllvm.git [ARM] Implement R_ARM_COPY relocation This adds support of copying objects from shared libraries. llvm-svn: 235705 --- diff --git a/lld/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.h b/lld/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.h index 8831807..0c33e88 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 6badc5e..e0d1582 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 _gotAtoms; + /// \brief Map Atoms to their Object entries. + llvm::MapVector _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(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(ref).setTarget(getObjectEntry(sla)); } else if (sla->type() == SharedLibraryAtom::Type::Code) { const_cast(ref).setTarget(getPLTEntry(sla, fromThumb)); } diff --git a/lld/test/elf/ARM/Inputs/libobj.so b/lld/test/elf/ARM/Inputs/libobj.so new file mode 100755 index 0000000..85b3ae4 Binary files /dev/null and b/lld/test/elf/ARM/Inputs/libobj.so differ diff --git a/lld/test/elf/ARM/Inputs/obj.c b/lld/test/elf/ARM/Inputs/obj.c new file mode 100644 index 0000000..fb6a9f1 --- /dev/null +++ b/lld/test/elf/ARM/Inputs/obj.c @@ -0,0 +1,4 @@ +static struct S { +} s; + +struct S *const object = &s; diff --git a/lld/test/elf/ARM/rel-copy.test b/lld/test/elf/ARM/rel-copy.test new file mode 100644 index 0000000..5d1d188 --- /dev/null +++ b/lld/test/elf/ARM/rel-copy.test @@ -0,0 +1,61 @@ +# Check handling of R_ARM_COPY relocation. +# RUN: yaml2obj -format=elf %s > %t-o.o +# RUN: lld -flavor gnu -target arm -m armelf_linux_eabi \ +# RUN: --noinhibit-exec %t-o.o -lobj -L%p/Inputs -o %t +# RUN: llvm-objdump -s -t %t | FileCheck %s +# RUN: llvm-readobj -relocations %t | FileCheck -check-prefix=READOBJ %s + +# CHECK: Contents of section .rel.dyn: +# CHECK-NEXT: 400138 00104000 14010000 +# addr = 0x401000 ^^ ^^ rel_type = 0x14 => R_ARM_COPY +# CHECK: SYMBOL TABLE: +# CHECK: 00401000 g .bss 00000004 object +# +# READOBJ: 0x401000 R_ARM_COPY object + +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_ARM + Flags: [ EF_ARM_EABI_VER5 ] +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000004 + Content: 80B483B000AF40F20003C0F200031B687B60002318460C37BD465DF8047B7047 + - Name: .rel.text + Type: SHT_REL + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .text + Relocations: + - Offset: 0x0000000000000006 + Symbol: object + Type: R_ARM_THM_MOVW_ABS_NC + - Offset: 0x000000000000000A + Symbol: object + Type: R_ARM_THM_MOVT_ABS + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' +Symbols: + Local: + - Name: '$t' + Section: .text + Global: + - Name: main + Type: STT_FUNC + Section: .text + Value: 0x0000000000000001 + - Name: object +...