From bf987c2dae19ff8bf4818292fb7f424c611592af Mon Sep 17 00:00:00 2001 From: Simon Atanasyan Date: Tue, 11 Feb 2014 05:34:02 +0000 Subject: [PATCH] [Mips] Handle R_MIPS_COPY relocation. llvm-svn: 201129 --- .../ELF/Mips/MipsLinkingContext.cpp | 13 ++++++ .../ELF/Mips/MipsLinkingContext.h | 2 + .../ELF/Mips/MipsRelocationPass.cpp | 41 ++++++++++++++++++ .../ELF/Mips/MipsTargetHandler.cpp | 1 + lld/test/elf/Mips/rcopy.test | 42 +++++++++++++++++++ 5 files changed, 99 insertions(+) create mode 100644 lld/test/elf/Mips/rcopy.test diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp b/lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp index 43578d5b4b0b..80343ff8befa 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp @@ -46,6 +46,19 @@ void MipsLinkingContext::addPasses(PassManager &pm) { ELFLinkingContext::addPasses(pm); } +bool MipsLinkingContext::isDynamicRelocation(const DefinedAtom &, + const Reference &r) const { + if (r.kindNamespace() != Reference::KindNamespace::ELF) + return false; + + switch (r.kindValue()) { + case llvm::ELF::R_MIPS_COPY: + return true; + default: + return false; + } +} + bool MipsLinkingContext::isPLTRelocation(const DefinedAtom &, const Reference &r) const { if (r.kindNamespace() != Reference::KindNamespace::ELF) diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h b/lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h index 17b42194965d..f44ff7ff979c 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h @@ -46,6 +46,8 @@ public: virtual StringRef getDefaultInterpreter() const; virtual void addPasses(PassManager &pm); virtual bool isRelaOutputFormat() const { return false; } + virtual bool isDynamicRelocation(const DefinedAtom &, + const Reference &r) const; virtual bool isPLTRelocation(const DefinedAtom &, const Reference &r) const; }; diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp b/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp index 3ec98c6930a2..78c879fce9d9 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp @@ -155,6 +155,11 @@ public: gotplt->setOrdinal(ordinal++); mf->addAtom(*gotplt); } + + for (auto obj : _objectVector) { + obj->setOrdinal(ordinal++); + mf->addAtom(*obj); + } } private: @@ -176,18 +181,30 @@ private: /// \brief Map Atoms to their PLT entries. llvm::DenseMap _pltMap; + /// \brief Map Atoms to their Object entries. + llvm::DenseMap _objectMap; + /// \brief the list of PLT atoms. std::vector _pltVector; /// \brief the list of GOTPLT atoms. std::vector _gotpltVector; + /// \brief the list of Object entries. + std::vector _objectVector; + /// \brief Handle a specific reference. void handleReference(const DefinedAtom &atom, const Reference &ref) { if (ref.kindNamespace() != lld::Reference::KindNamespace::ELF) return; assert(ref.kindArch() == Reference::KindArch::Mips); switch (ref.kindValue()) { + case R_MIPS_32: + case R_MIPS_HI16: + case R_MIPS_LO16: + // FIXME (simon): Handle dynamic/static linking differently. + handlePlain(ref); + break; case R_MIPS_26: handlePLT(ref); break; @@ -204,6 +221,14 @@ private: return false; } + void handlePlain(const Reference &ref) { + if (!ref.target()) + return; + auto sla = dyn_cast(ref.target()); + if (sla && sla->type() == SharedLibraryAtom::Type::Data) + const_cast(ref).setTarget(getObjectEntry(sla)); + } + void handlePLT(const Reference &ref) { if (ref.kindValue() == R_MIPS_26 && !isLocal(ref.target())) const_cast(ref).setKindValue(LLD_R_MIPS_GLOBAL_26); @@ -332,6 +357,22 @@ private: return pa; } + + const ObjectAtom *getObjectEntry(const SharedLibraryAtom *a) { + auto obj = _objectMap.find(a); + if (obj != _objectMap.end()) + return obj->second; + + auto oa = new (_file._alloc) ObjectAtom(_file); + oa->addReferenceELF_Mips(R_MIPS_COPY, 0, oa, 0); + oa->_name = a->name(); + oa->_size = a->size(); + + _objectMap[a] = oa; + _objectVector.push_back(oa); + + return oa; + } }; } // end anon namespace diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp b/lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp index be3d1e466cb9..84ee9636a0c3 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp @@ -56,6 +56,7 @@ const Registry::KindStrings MipsTargetHandler::kindStrings[] = { LLD_KIND_STRING_ENTRY(R_MIPS_GOT16), LLD_KIND_STRING_ENTRY(R_MIPS_CALL16), LLD_KIND_STRING_ENTRY(R_MIPS_JALR), + LLD_KIND_STRING_ENTRY(R_MIPS_COPY), LLD_KIND_STRING_ENTRY(R_MIPS_JUMP_SLOT), LLD_KIND_STRING_ENTRY(LLD_R_MIPS_GLOBAL_GOT), LLD_KIND_STRING_ENTRY(LLD_R_MIPS_GLOBAL_GOT16), diff --git a/lld/test/elf/Mips/rcopy.test b/lld/test/elf/Mips/rcopy.test new file mode 100644 index 000000000000..5184959d0f25 --- /dev/null +++ b/lld/test/elf/Mips/rcopy.test @@ -0,0 +1,42 @@ +# Check handling of R_MIPS_COPY relocation + +# Build shared library +# RUN: llvm-mc -triple=mipsel -filetype=obj -relocation-model=pic \ +# RUN: -o=%t-obj %p/Inputs/ext.s +# RUN: lld -flavor gnu -target mipsel -shared -o %t-so %t-obj + +# Build executable +# RUN: llvm-mc -triple=mipsel -filetype=obj -o=%t-obj %s +# RUN: lld -flavor gnu -target mipsel -e glob -o %t %t-obj %t-so +# RUN: llvm-readobj -relocations -symbols -dyn-symbols %t | FileCheck %s + +# CHECK: Relocations [ +# CHECK-NEXT: Section ({{[0-9]+}}) .rel.dyn { +# CHECK-NEXT: 0x{{[1-9A-F][0-9A-F]*}} R_MIPS_COPY data1 0x0 +# CHECK-NEXT: } +# CHECK-NEXT: ] + +# CHECK: Name: data1 ({{[0-9]+}} +# CHECK-NEXT: Value: 0x{{[1-9A-F][0-9A-F]*}} +# CHECK-NEXT: Size: 4 +# CHECK-NEXT: Binding: Global (0x1) +# CHECK-NEXT: Type: Object (0x1) +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: .bss (0x{{[1-9A-F][0-9A-F]*}}) + +# CHECK: Name: data1@ ({{[0-9]+}} +# CHECK-NEXT: Value: 0x{{[1-9A-F][0-9A-F]*}} +# CHECK-NEXT: Size: 4 +# CHECK-NEXT: Binding: Global (0x1) +# CHECK-NEXT: Type: Object (0x1) +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: .bss (0x{{[1-9A-F][0-9A-F]*}}) + + .abicalls + .option pic0 + .global glob + .ent glob +glob: + lui $2,%hi(data1) + lw $2,%lo(data1)($2) + .end glob