From c3431bf67be0baabb8756facd091728ad853772f Mon Sep 17 00:00:00 2001 From: Denis Protivensky Date: Fri, 24 Apr 2015 08:53:02 +0000 Subject: [PATCH] [ARM] Implement R_ARM_COPY relocation This adds support of copying objects from shared libraries. llvm-svn: 235705 --- lld/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.h | 8 +++ lld/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp | 35 +++++++++++- lld/test/elf/ARM/Inputs/libobj.so | Bin 0 -> 5067 bytes lld/test/elf/ARM/Inputs/obj.c | 4 ++ lld/test/elf/ARM/rel-copy.test | 61 +++++++++++++++++++++ 5 files changed, 106 insertions(+), 2 deletions(-) create mode 100755 lld/test/elf/ARM/Inputs/libobj.so create mode 100644 lld/test/elf/ARM/Inputs/obj.c create mode 100644 lld/test/elf/ARM/rel-copy.test 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 0000000000000000000000000000000000000000..85b3ae4ca3d19ffb0f7dbf1af4bc0154308a2ffc GIT binary patch literal 5067 zcmb_gU2Ggz6~43UpS5d(lWtnqj?l>LgR5r8PGS|iL=ea8zu1ncYosD74YRxBc+=e- zGdnJJjM_d_NR@(uphB%$6e%z8fGR5JLutdGs#28-1tRVkfrUW&VtQSHag6JTN?HRWCq|2Y~*Xu$+Tlw&96ZUXHX`K?e5K}2=zn6 z_MKqj(%>X`;`C=#__g~6->xTqXt(tBJU;pB$L1co@?F{vfcJyhW*_)QL@b|;{ieWJ z64eI23CuA+0&WL)fIkY}i(Y3Zprmf8l#S;$`hGR9OXjZ^;!sStQGNnE)MD_R>Y(}# z^y4x8D?99Ibqn;A*$g~mhx+y|yy*#*ARD{_?gXCCw;xaQJY>B8@9)yT3Ozm_54wfy zH8YiXnbXo1zgpDghJ;WPGgBu=-J=fA2Z{bnuQ$K#GHqOI)_)n2>p)7EN^qHk`ia)e z+TV&Y&kE(Ch8)BmQ@0@x!hbT9*rYy6INV`MINSgwI`4wK1-L_$u%}LB{|p~}GxhN0 zYfT&3&8CfuoBK8{Y^2`$(PlbKGQX^JfVL4 zE^zOFe+KRXJ~h=g**3ifd|UT=?$J)`&0l?Ssxx_|`P7qJZC(QQMet+b4BI^0KHZKn zdREWn?tiWgy?^|f)bx6;YpMR;rN7nRyIgOXwtCld-OH)VUq_ofnCJdM$PnB*nR>Q$ zdNr3=TF)JL?(((NiRZ62VLWxm^(&80ynFR7>`O0jHpjwRah=5Pe~)$k77ql7d&vFc z`KBN9yz_kB2FX3^fh4pW%)R6KP$ypp^C(7e62^)JbjDcm3YhVOKEcq?fjy%iQRg!- zE^+T)g^}e)AQ`VF!8d~$hj`9O|Ekx6BJ6cY&h;(GPeFelvhfHS_uu{)i-oSCJ$Wyp zUrvmU-eva{!k|`*f}or|Jz7Eh(qCRz)i# zqflwg1AbU51=Ssj3mYa!yeTY~BjxDWCS3)2)KNjZg}Qt_*(8=0SVyeJAw`IQKf?0+WuCEr!_tJfNwffN$o za8N-XC64||z7H(hPaK)?jy_8q{g`ZnX(N`B{(HQk6Gy)%)8B=}%W|lo&k{#}C1+5U zaam8k8%!T(nSM^TQRaB;i<0yOFyG6>@w||EULZ6P$8%Ex3y$ZDEa#ACQ*a^5?4ReB z=bp?MASB~fP$4)uH-`lTNgR0emO4lnV}otUWJ|g z4S-3+6--h8(?(J?U)&n79U zchsCgqcakjvu1Rz{B~X_d9l26lKL%a&WOP?@|d$=baN8v^G4@e+4#26O-9f6v(Zgv zPJcBzS5EE7!>P+VFsa|R=Dp1Nq<-rn2EtE_p4L+G;3V?$I3>5<&Zahrw|QeJbw!i< zdwmWi#sEV%>3e|a2}D{KhJl!!c*&!=>(nLBXJpEoj`Y9u|EDd-F!+wfdJ+G<=_t^fGTG(F>3SPNCU#j*yPQMpcvdDv1Rd zfI=9RoIqtfg`UdpmwfMjcd@E6MfLw1po#%7PAytlTyzS!+nySocW0*VS-|Bs6RGVR zw;NU50`J^4C0FfOmFpG*_e?p+du6v61!2wgR#p`<)#b7u`9)`F_|5@zz6VHO?@i+C zBC8G8lunM_;!35mh9)she-GFJ#pNB7t^qbaKQcS!j-AfwOF17x%EemXE_u}=KNRFX zcY0)YY7}^UKoG>l%-qS58Fy}c{GPD|cVXn@%os2E@h=A_PHf-p|Kpd4?T-eW2frZ5 p_W|=!!Fu$cDvI(zhLMI$)4=|FrqIZ{|0B#z19E# literal 0 HcmV?d00001 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 +... -- 2.7.4