[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