[lld] r234588 - [ARM] Implement PLT for dynamic pass
Denis Protivensky
dprotivensky at accesssoftek.com
Fri Apr 10 04:41:27 PDT 2015
Author: denis-protivensky
Date: Fri Apr 10 06:41:27 2015
New Revision: 234588
URL: http://llvm.org/viewvc/llvm-project?rev=234588&view=rev
Log:
[ARM] Implement PLT for dynamic pass
This includes implementation of PLT0 entry.
For testing, libfn.so binary is added since
there's no way to link shared objects with lld yet.
Added:
lld/trunk/test/elf/ARM/Inputs/
lld/trunk/test/elf/ARM/Inputs/fn.c
lld/trunk/test/elf/ARM/Inputs/libfn.so (with props)
lld/trunk/test/elf/ARM/plt-dynamic.test
Modified:
lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp
lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp
Modified: lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp?rev=234588&r1=234587&r2=234588&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp Fri Apr 10 06:41:27 2015
@@ -592,6 +592,7 @@ std::error_code ARMTargetRelocationHandl
case R_ARM_LDR_PC_G2:
relocR_ARM_LDR_PC_G2(loc, reloc, target, addend);
break;
+ case R_ARM_JUMP_SLOT:
case R_ARM_IRELATIVE:
// Runtime only relocations. Ignore here.
break;
Modified: lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp?rev=234588&r1=234587&r2=234588&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp Fri Apr 10 06:41:27 2015
@@ -53,6 +53,15 @@ static const uint8_t Veneer_THM_B_BL_Sta
// .got values
static const uint8_t ARMGotAtomContent[4] = {0};
+// .plt value (entry 0)
+static const uint8_t ARMPlt0AtomContent[20] = {
+ 0x04, 0xe0, 0x2d, 0xe5, // push {lr}
+ 0x04, 0xe0, 0x9f, 0xe5, // ldr lr, [pc, #4]
+ 0x0e, 0xe0, 0x8f, 0xe0, // add lr, pc, lr
+ 0x00, 0xf0, 0xbe, 0xe5, // ldr pc, [lr, #0]!
+ 0x00, 0x00, 0x00, 0x00 // <got1_symbol_address>
+};
+
// .plt values (other entries)
static const uint8_t ARMPltAtomContent[12] = {
0x00, 0xc0, 0x8f, 0xe2, // add ip, pc, #offset[G0]
@@ -200,6 +209,41 @@ public:
ARMGOTPLTAtom(const File &f) : ARMGOTAtom(f, ".got.plt") {}
};
+/// \brief PLT0 entry atom.
+/// Serves as a mapping symbol in the release mode.
+class ARMPLT0Atom : public PLT0Atom {
+public:
+ ARMPLT0Atom(const File &f, const std::string &name)
+ : PLT0Atom(f) {
+#ifndef NDEBUG
+ _name = name;
+#else
+ // Don't move the code to any base classes since
+ // virtual codeModel method would return wrong value.
+ _name = getMappingAtomName(codeModel(), name);
+#endif
+ }
+
+ DefinedAtom::CodeModel codeModel() const override {
+#ifndef NDEBUG
+ return DefinedAtom::codeNA;
+#else
+ return DefinedAtom::codeARM_a;
+#endif
+ }
+
+ ArrayRef<uint8_t> rawContent() const override {
+ return llvm::makeArrayRef(ARMPlt0AtomContent);
+ }
+
+ Alignment alignment() const override { return 4; }
+
+ StringRef name() const override { return _name; }
+
+private:
+ std::string _name;
+};
+
/// \brief PLT entry atom.
/// Serves as a mapping symbol in the release mode.
class ARMPLTAtom : public PLTAtom {
@@ -585,6 +629,10 @@ public:
// Add all created atoms to the link.
uint64_t ordinal = 0;
+ if (_plt0) {
+ _plt0->setOrdinal(ordinal++);
+ mf->addAtom(*_plt0);
+ }
for (auto &pltKV : _pltAtoms) {
auto &plt = pltKV.second;
if (auto *v = plt._veneer) {
@@ -599,6 +647,12 @@ public:
_null->setOrdinal(ordinal++);
mf->addAtom(*_null);
}
+ if (_plt0) {
+ _got0->setOrdinal(ordinal++);
+ mf->addAtom(*_got0);
+ _got1->setOrdinal(ordinal++);
+ mf->addAtom(*_got1);
+ }
for (auto &gotKV : _gotAtoms) {
auto &got = gotKV.second;
got->setOrdinal(ordinal++);
@@ -656,6 +710,14 @@ protected:
/// \brief GOT entry that is always 0. Used for undefined weaks.
GOTAtom *_null = nullptr;
+
+ /// \brief The got and plt entries for .PLT0. This is used to call into the
+ /// dynamic linker for symbol resolution.
+ /// @{
+ PLT0Atom *_plt0 = nullptr;
+ GOTAtom *_got0 = nullptr;
+ GOTAtom *_got1 = nullptr;
+ /// @}
};
/// This implements the static relocation model. Meaning GOT and PLT entries are
@@ -737,8 +799,36 @@ public:
ARMDynamicRelocationPass(const elf::ARMLinkingContext &ctx)
: ARMRelocationPass(ctx) {}
+ /// \brief get the PLT entry for a given atom.
+ const PLTAtom *getPLTEntry(const SharedLibraryAtom *sla, bool fromThumb) {
+ return getPLT(sla, fromThumb, &ARMDynamicRelocationPass::createPLTGOT);
+ }
+
+ /// \brief Create the GOT entry for a given atom.
+ const GOTAtom *createPLTGOT(const Atom *da) {
+ assert(!_gotAtoms.lookup(da) && "PLTGOT entry already exists");
+ auto g = new (_file._alloc) ARMGOTPLTAtom(_file);
+ g->addReferenceELF_ARM(R_ARM_ABS32, 0, getPLT0(), 0);
+ g->addReferenceELF_ARM(R_ARM_JUMP_SLOT, 0, da, 0);
+#ifndef NDEBUG
+ g->_name = "__got_plt0_";
+ g->_name += da->name();
+#endif
+ _gotAtoms[da] = g;
+ return g;
+ }
+
/// \brief Handle ordinary relocation references.
std::error_code handlePlain(const DefinedAtom &atom, const Reference &ref) {
+ if (auto sla = dyn_cast<SharedLibraryAtom>(ref.target())) {
+ if (sla->type() == SharedLibraryAtom::Type::Data) {
+ llvm_unreachable("Handle object entries");
+ } else if (sla->type() == SharedLibraryAtom::Type::Code) {
+ const_cast<Reference &>(ref)
+ .setTarget(getPLTEntry(sla, isThumbCode(atom.codeModel())));
+ }
+ return std::error_code();
+ }
return handleIFUNC(atom, ref);
}
@@ -759,6 +849,24 @@ public:
llvm_unreachable("Handle TLS TPOFF32");
}
+ const PLT0Atom *getPLT0() {
+ if (_plt0)
+ return _plt0;
+ // Fill in the null entry.
+ getNullGOT();
+ _plt0 = new (_file._alloc) ARMPLT0Atom(_file, "__PLT0");
+ _got0 = new (_file._alloc) ARMGOTPLTAtom(_file);
+ _got1 = new (_file._alloc) ARMGOTPLTAtom(_file);
+ _plt0->addReferenceELF_ARM(R_ARM_REL32, 16, _got1, 0);
+ // Fake reference to show connection between the GOT and PLT entries.
+ _plt0->addReferenceELF_ARM(R_ARM_NONE, 0, _got0, 0);
+#ifndef NDEBUG
+ _got0->_name = "__got0";
+ _got1->_name = "__got1";
+#endif
+ return _plt0;
+ }
+
std::error_code handleGOT(const Reference &ref) {
if (isa<const SharedLibraryAtom>(ref.target())) {
llvm_unreachable("Handle shared GOT entries");
Added: lld/trunk/test/elf/ARM/Inputs/fn.c
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/ARM/Inputs/fn.c?rev=234588&view=auto
==============================================================================
--- lld/trunk/test/elf/ARM/Inputs/fn.c (added)
+++ lld/trunk/test/elf/ARM/Inputs/fn.c Fri Apr 10 06:41:27 2015
@@ -0,0 +1 @@
+int fn() { return 1; }
Added: lld/trunk/test/elf/ARM/Inputs/libfn.so
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/ARM/Inputs/libfn.so?rev=234588&view=auto
==============================================================================
Binary file - no diff available.
Propchange: lld/trunk/test/elf/ARM/Inputs/libfn.so
------------------------------------------------------------------------------
svn:executable = *
Propchange: lld/trunk/test/elf/ARM/Inputs/libfn.so
------------------------------------------------------------------------------
svn:mime-type = application/x-sharedlib
Added: lld/trunk/test/elf/ARM/plt-dynamic.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/ARM/plt-dynamic.test?rev=234588&view=auto
==============================================================================
--- lld/trunk/test/elf/ARM/plt-dynamic.test (added)
+++ lld/trunk/test/elf/ARM/plt-dynamic.test Fri Apr 10 06:41:27 2015
@@ -0,0 +1,142 @@
+# Check that PLT entries are properly generated when link dynamically.
+#
+# 1. ARM code generates PLT entries.
+# RUN: yaml2obj -format=elf -docnum 1 %s > %t-arm.o
+# RUN: lld -flavor gnu -target arm-linux-gnu \
+# RUN: --noinhibit-exec %t-arm.o -lfn -L%p/Inputs -o %t
+# RUN: llvm-objdump -s %t | FileCheck -check-prefix=ARM %s
+
+# ARM: Contents of section .rel.plt:
+# ARM-NEXT: 400134 0c104000 16010000
+# GOT addr = 0x40100c ^^
+# ARM-NEXT: Contents of section .plt:
+# ARM-NEXT: 40013c 04e02de5 04e09fe5 0ee08fe0 00f0bee5
+# ^ -- PLT0 --
+# ARM-NEXT: 40014c bc0e0000 00c68fe2 00ca8ce2 b4febce5
+# -- ^ ^ -- PLT_fn -- ^
+# ARM-NEXT: Contents of section .text:
+# ARM-NEXT: 40015c {{[0-9a-f]+}} {{[0-9a-f]+}} f9ffffea
+# b PLT_fn ^^
+# ARM: Contents of section .got.plt:
+# ARM-NEXT: 401000 00000000 00000000 00000000 3c014000
+# PLT0 addr = 0x40013c ^^
+
+# 2. Thumb code generates PLT entries with veneers.
+# RUN: yaml2obj -format=elf -docnum 2 %s > %t-thm.o
+# RUN: lld -flavor gnu -target arm-linux-gnu \
+# RUN: --noinhibit-exec %t-thm.o -lfn -L%p/Inputs -o %t
+# RUN: llvm-objdump -s %t | FileCheck -check-prefix=THM %s
+
+# THM: Contents of section .rel.plt:
+# THM-NEXT: 400134 0c104000 16010000
+# GOT addr = 0x40100c ^^
+# THM-NEXT: Contents of section .plt:
+# THM-NEXT: 40013c 04e02de5 04e09fe5 0ee08fe0 00f0bee5
+# ^ -- PLT0 --
+# THM-NEXT: 40014c bc0e0000 78470000 00c68fe2 00ca8ce2
+# -- ^ veneer ^ ^ -- PLT_fn --
+# THM-NEXT: 40015c b0febce5
+# -- ^
+# THM: Contents of section .text:
+# THM-NEXT: 400160 {{[0-9a-f]+}} fff7f4bf
+# b PLT_fn ^^
+
+# Generation of mapping symbols.
+# RUN: yaml2obj -format=elf -docnum 1 %s > %t-arm.o
+# RUN: lld -flavor gnu -target arm-linux-gnu \
+# RUN: --noinhibit-exec %t-arm.o -lfn -L%p/Inputs -o %t-arm
+# RUN: llvm-readobj -symbols %t-arm | FileCheck -check-prefix=ARM-MAPPING %s
+
+# ARM-MAPPING: Name: {{[$]?[a]?[.]?}}__PLT0
+# ARM-MAPPING: Name: {{[$]?[a]?[.]?}}__plt_fn
+
+# RUN: yaml2obj -format=elf -docnum 2 %s > %t-thm.o
+# RUN: lld -flavor gnu -target arm-linux-gnu \
+# RUN: --noinhibit-exec %t-thm.o -lfn -L%p/Inputs -o %t-thm
+# RUN: llvm-readobj -symbols %t-thm | FileCheck -check-prefix=THM-MAPPING %s
+
+# THM-MAPPING: Name: {{[$]?[a]?[.]?}}__PLT0
+# THM-MAPPING: Name: {{[$]?[t]?[.]?}}__plt_from_thumb_fn
+# THM-MAPPING: Name: {{[$]?[a]?[.]?}}__plt_fn
+
+# arm.o
+---
+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: 00482DE904B08DE2FEFFFFEA0030A0E10300A0E10088BDE8
+ - Name: .rel.text
+ Type: SHT_REL
+ Link: .symtab
+ AddressAlign: 0x0000000000000004
+ Info: .text
+ Relocations:
+ - Offset: 0x0000000000000008
+ Symbol: fn
+ Type: R_ARM_JUMP24
+ - 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:
+ Global:
+ - Name: main
+ Type: STT_FUNC
+ Section: .text
+ - Name: fn
+
+# thm.o
+---
+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: 80B500AFFFF7FEBF0346184680BD00BF
+ - Name: .rel.text
+ Type: SHT_REL
+ Link: .symtab
+ AddressAlign: 0x0000000000000004
+ Info: .text
+ Relocations:
+ - Offset: 0x0000000000000004
+ Symbol: fn
+ Type: R_ARM_THM_JUMP24
+ - 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:
+ Global:
+ - Name: main
+ Type: STT_FUNC
+ Section: .text
+ Value: 0x0000000000000001
+ - Name: fn
+...
More information about the llvm-commits
mailing list