[lld] r233900 - [ARM] Generate PLT entries for calls from ARM and Thumb code

Denis Protivensky dprotivensky at accesssoftek.com
Thu Apr 2 00:23:11 PDT 2015


Author: denis-protivensky
Date: Thu Apr  2 02:23:11 2015
New Revision: 233900

URL: http://llvm.org/viewvc/llvm-project?rev=233900&view=rev
Log:
[ARM] Generate PLT entries for calls from ARM and Thumb code

The function call that goes through PLT table may be performed
from both ARM and Thumb code.
This situation requires adding a veneer to original PLT code
(which is always ARM) to effect Thumb-to-ARM transition.

Differential Revision: http://reviews.llvm.org/D8701

Added:
    lld/trunk/test/elf/ARM/plt-interwork.test
Modified:
    lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp
    lld/trunk/test/elf/ARM/rel-ifunc.test

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=233900&r1=233899&r2=233900&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp Thu Apr  2 02:23:11 2015
@@ -20,7 +20,7 @@
 #include "ARMLinkingContext.h"
 #include "Atoms.h"
 #include "lld/Core/Simple.h"
-#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/Debug.h"
 
@@ -51,13 +51,15 @@ static const uint8_t ARMGotAtomContent[4
 
 // .plt values (other entries)
 static const uint8_t ARMPltAtomContent[12] = {
-    0x00, 0xc0, 0x8f,
-    0xe2, // add    ip, pc, #offset[G0]
-    0x00, 0xc0, 0x8c,
-    0xe2, // add    ip, ip, #offset[G1]
+    0x00, 0xc0, 0x8f, 0xe2,  // add ip, pc, #offset[G0]
+    0x00, 0xc0, 0x8c, 0xe2,  // add ip, ip, #offset[G1]
+    0x00, 0xf0, 0xbc, 0xe5   // ldr pc, [ip, #offset[G2]]!
+};
 
-    0x00, 0xf0, 0xbc,
-    0xe5, // ldr    pc, [ip, #offset[G2]]!
+// Veneer for switching from Thumb to ARM code for PLT entries.
+static const uint8_t ARMPltVeneerAtomContent[4] = {
+    0x78, 0x47,              // bx pc
+    0x00, 0x00               // nop
 };
 
 /// \brief Atoms that hold veneer code.
@@ -121,22 +123,48 @@ public:
 /// \brief Atoms that are used by ARM dynamic linking
 class ARMGOTAtom : public GOTAtom {
 public:
-  ARMGOTAtom(const File &f, StringRef secName) : GOTAtom(f, secName) {}
+  ARMGOTAtom(const File &f) : GOTAtom(f, ".got") {}
 
   ArrayRef<uint8_t> rawContent() const override {
     return llvm::makeArrayRef(ARMGotAtomContent);
   }
 
   Alignment alignment() const override { return 4; }
+
+protected:
+  // Constructor for PLTGOT atom.
+  ARMGOTAtom(const File &f, StringRef secName) : GOTAtom(f, secName) {}
+};
+
+class ARMGOTPLTAtom : public ARMGOTAtom {
+public:
+  ARMGOTPLTAtom(const File &f) : ARMGOTAtom(f, ".got.plt") {}
 };
 
 class ARMPLTAtom : public PLTAtom {
 public:
-  ARMPLTAtom(const File &f, StringRef secName) : PLTAtom(f, secName) {}
+  ARMPLTAtom(const File &f) : PLTAtom(f, ".plt") {}
 
   ArrayRef<uint8_t> rawContent() const override {
     return llvm::makeArrayRef(ARMPltAtomContent);
   }
+
+  Alignment alignment() const override { return 4; }
+};
+
+class ARMPLTVeneerAtom : public PLTAtom {
+public:
+  ARMPLTVeneerAtom(const File &f) : PLTAtom(f, ".plt") {}
+
+  DefinedAtom::CodeModel codeModel() const override {
+    return DefinedAtom::codeARMThumb;
+  }
+
+  ArrayRef<uint8_t> rawContent() const override {
+    return llvm::makeArrayRef(ARMPltVeneerAtomContent);
+  }
+
+  Alignment alignment() const override { return 4; }
 };
 
 class ELFPassFile : public SimpleFile {
@@ -172,7 +200,7 @@ template <class Derived> class ARMReloca
     case R_ARM_JUMP24:
     case R_ARM_THM_JUMP24:
     case R_ARM_THM_JUMP11:
-      static_cast<Derived *>(this)->handleIFUNC(ref);
+      static_cast<Derived *>(this)->handleIFUNC(atom, ref);
       static_cast<Derived *>(this)->handleVeneer(atom, ref);
       break;
     case R_ARM_TLS_IE32:
@@ -188,10 +216,15 @@ template <class Derived> class ARMReloca
 
 protected:
   std::error_code handleVeneer(const DefinedAtom &atom, const Reference &ref) {
+    const VeneerAtom *(Derived::*getVeneer)(const DefinedAtom *, StringRef) =
+        nullptr;
     const auto kindValue = ref.kindValue();
     switch (kindValue) {
     case R_ARM_JUMP24:
+      getVeneer = &Derived::getVeneer_ARM_B_BL;
+      break;
     case R_ARM_THM_JUMP24:
+      getVeneer = &Derived::getVeneer_THM_B_BL;
       break;
     default:
       return std::error_code();
@@ -226,19 +259,9 @@ protected:
       llvm_unreachable(errStr.c_str());
     }
 
-    const Atom *veneer = nullptr;
-    switch (kindValue) {
-    case R_ARM_JUMP24:
-      veneer = static_cast<Derived *>(this)
-                   ->getVeneer_ARM_B_BL(target, secName);
-      break;
-    case R_ARM_THM_JUMP24:
-      veneer = static_cast<Derived *>(this)
-                   ->getVeneer_THM_B_BL(target, secName);
-      break;
-    default:
-      llvm_unreachable("Unhandled reference type for veneer generation");
-    }
+    assert(getVeneer && "The veneer handler is missing");
+    const Atom *veneer =
+        (static_cast<Derived *>(this)->*getVeneer)(target, secName);
 
     assert(veneer && "The veneer is not set");
     const_cast<Reference &>(ref).setTarget(veneer);
@@ -257,64 +280,113 @@ protected:
   /// \brief Create a GOT entry for TLS with reloc type and addend specified.
   template <Reference::KindValue R_ARM_TLS, Reference::Addend A = 0>
   const GOTAtom *getGOTTLSEntry(const DefinedAtom *da) {
-    auto got = _gotMap.find(da);
-    if (got != _gotMap.end())
-      return got->second;
-    auto g = new (_file._alloc) ARMGOTAtom(_file, ".got");
+    if (auto got = _gotAtoms.lookup(da))
+      return got;
+    auto g = new (_file._alloc) ARMGOTAtom(_file);
     g->addReferenceELF_ARM(R_ARM_TLS, 0, da, A);
 #ifndef NDEBUG
     g->_name = "__got_tls_";
     g->_name += da->name();
 #endif
-    _gotMap[da] = g;
-    _gotVector.push_back(g);
+    _gotAtoms[da] = g;
     return g;
   }
 
-  /// \brief Create a PLT entry referencing PLTGOT entry.
+  /// \brief get a veneer for a PLT entry.
+  const PLTAtom *getPLTVeneer(const DefinedAtom *da, PLTAtom *pa,
+                              StringRef source) {
+    auto va = new (_file._alloc) ARMPLTVeneerAtom(_file);
+    // Fake reference to show connection between veneer and PLT entry.
+    va->addReferenceELF_ARM(R_ARM_NONE, 0, pa, 0);
+#ifndef NDEBUG
+    va->_name = "__plt_from_thumb";
+    va->_name += source;
+    va->_name += da->name();
+#endif
+    _pltAtoms[da] = PLTWithVeneer(pa, va);
+    return va;
+  }
+
+  typedef const GOTAtom *(Derived::*GOTFactory)(const DefinedAtom *);
+
+  /// \brief get a PLT entry referencing PLTGOT entry.
   ///
-  /// The function creates the PLT entry object and passes ownership
-  /// over it to the caller.
-  PLTAtom *createPLTforGOT(const GOTAtom *ga) {
-    auto pa = new (_file._alloc) ARMPLTAtom(_file, ".plt");
+  /// If the entry does not exist, both GOT and PLT entry are created.
+  const PLTAtom *getPLTEntry(const DefinedAtom *da, bool fromThumb,
+                             GOTFactory gotFactory, StringRef source) {
+    auto pltVeneer = _pltAtoms.lookup(da);
+    if (!pltVeneer.empty()) {
+      // Return clean PLT entry provided it is ARM code.
+      if (!fromThumb)
+        return pltVeneer._plt;
+
+      // Check if veneer is present for Thumb to ARM transition.
+      if (pltVeneer._veneer)
+        return pltVeneer._veneer;
+
+      // Create veneer for existing PLT entry.
+      return getPLTVeneer(da, pltVeneer._plt, source);
+    }
+
+    // Create specific GOT entry.
+    const auto *ga = (static_cast<Derived *>(this)->*gotFactory)(da);
+    assert(_gotAtoms.lookup(da) == ga &&
+           "GOT entry should be added to the map");
+    assert(ga->customSectionName() == ".got.plt" &&
+           "GOT entry should be in a special section");
+
+    // Create PLT entry for the GOT entry.
+    auto pa = new (_file._alloc) ARMPLTAtom(_file);
     pa->addReferenceELF_ARM(R_ARM_ALU_PC_G0_NC, 0, ga, -8);
     pa->addReferenceELF_ARM(R_ARM_ALU_PC_G1_NC, 4, ga, -4);
     pa->addReferenceELF_ARM(R_ARM_LDR_PC_G2, 8, ga, 0);
+#ifndef NDEBUG
+    pa->_name = "__plt";
+    pa->_name += source;
+    pa->_name += da->name();
+#endif
+    // Since all PLT entries are in ARM code, Thumb to ARM
+    // switching should be added if the relocated place contais Thumb code.
+    if (fromThumb)
+      return getPLTVeneer(da, pa, source);
+
+    // Otherwise just add PLT entry and return it to the caller.
+    _pltAtoms[da] = PLTWithVeneer(pa);
     return pa;
   }
 
+  /// \brief Create the GOT entry for a given IFUNC Atom.
+  const GOTAtom *createIFUNCGOTEntry(const DefinedAtom *da) {
+    assert(!_gotAtoms.lookup(da) && "IFUNC GOT entry already exists");
+    auto g = new (_file._alloc) ARMGOTPLTAtom(_file);
+    g->addReferenceELF_ARM(R_ARM_ABS32, 0, da, 0);
+    g->addReferenceELF_ARM(R_ARM_IRELATIVE, 0, da, 0);
+#ifndef NDEBUG
+    g->_name = "__got_ifunc_";
+    g->_name += da->name();
+#endif
+    _gotAtoms[da] = g;
+    return g;
+  }
+
   /// \brief get the PLT entry for a given IFUNC Atom.
-  ///
-  /// If the entry does not exist. Both the GOT and PLT entry is created.
-  const PLTAtom *getIFUNCPLTEntry(const DefinedAtom *da) {
-    auto plt = _pltMap.find(da);
-    if (plt != _pltMap.end())
-      return plt->second;
-    auto ga = new (_file._alloc) ARMGOTAtom(_file, ".got.plt");
-    ga->addReferenceELF_ARM(R_ARM_ABS32, 0, da, 0);
-    ga->addReferenceELF_ARM(R_ARM_IRELATIVE, 0, da, 0);
-    auto pa = createPLTforGOT(ga);
+  const PLTAtom *getIFUNCPLTEntry(const DefinedAtom *da, bool fromThumb) {
+    StringRef source;
 #ifndef NDEBUG
-    ga->_name = "__got_ifunc_";
-    ga->_name += da->name();
-    pa->_name = "__plt_ifunc_";
-    pa->_name += da->name();
+    source = "_ifunc_";
 #endif
-    _gotMap[da] = ga;
-    _pltMap[da] = pa;
-    _gotVector.push_back(ga);
-    _pltVector.push_back(pa);
-    return pa;
+    return getPLTEntry(da, fromThumb, &Derived::createIFUNCGOTEntry, source);
   }
 
   /// \brief Redirect the call to the PLT stub for the target IFUNC.
   ///
   /// This create a PLT and GOT entry for the IFUNC if one does not exist. The
   /// GOT entry and a IRELATIVE relocation to the original target resolver.
-  std::error_code handleIFUNC(const Reference &ref) {
+  std::error_code handleIFUNC(const DefinedAtom &atom, const Reference &ref) {
     auto target = dyn_cast<const DefinedAtom>(ref.target());
     if (target && target->contentType() == DefinedAtom::typeResolver) {
-      const_cast<Reference &>(ref).setTarget(getIFUNCPLTEntry(target));
+      const_cast<Reference &>(ref).setTarget(
+          getIFUNCPLTEntry(target, isThumbCode(atom.codeModel())));
     }
     return std::error_code();
   }
@@ -322,7 +394,7 @@ protected:
   /// \brief Create a GOT entry containing 0.
   const GOTAtom *getNullGOT() {
     if (!_null) {
-      _null = new (_file._alloc) ARMGOTAtom(_file, ".got.plt");
+      _null = new (_file._alloc) ARMGOTPLTAtom(_file);
 #ifndef NDEBUG
       _null->_name = "__got_null";
 #endif
@@ -331,17 +403,15 @@ protected:
   }
 
   const GOTAtom *getGOT(const DefinedAtom *da) {
-    auto got = _gotMap.find(da);
-    if (got != _gotMap.end())
-      return got->second;
-    auto g = new (_file._alloc) ARMGOTAtom(_file, ".got");
+    if (auto got = _gotAtoms.lookup(da))
+      return got;
+    auto g = new (_file._alloc) ARMGOTAtom(_file);
     g->addReferenceELF_ARM(R_ARM_ABS32, 0, da, 0);
 #ifndef NDEBUG
     g->_name = "__got_";
     g->_name += da->name();
 #endif
-    _gotMap[da] = g;
-    _gotVector.push_back(g);
+    _gotAtoms[da] = g;
     return g;
   }
 
@@ -392,19 +462,27 @@ public:
 
     // Add all created atoms to the link.
     uint64_t ordinal = 0;
-    for (auto &plt : _pltVector) {
-      plt->setOrdinal(ordinal++);
-      mf->addAtom(*plt);
+    for (auto &pltKV : _pltAtoms) {
+      auto &plt = pltKV.second;
+      if (auto *v = plt._veneer) {
+        v->setOrdinal(ordinal++);
+        mf->addAtom(*v);
+      }
+      auto *p = plt._plt;
+      p->setOrdinal(ordinal++);
+      mf->addAtom(*p);
     }
     if (_null) {
       _null->setOrdinal(ordinal++);
       mf->addAtom(*_null);
     }
-    for (auto &got : _gotVector) {
+    for (auto &gotKV : _gotAtoms) {
+      auto &got = gotKV.second;
       got->setOrdinal(ordinal++);
       mf->addAtom(*got);
     }
-    for (auto &veneer : _veneerVector) {
+    for (auto &veneerKV : _veneerAtoms) {
+      auto &veneer = veneerKV.second;
       veneer->setOrdinal(ordinal++);
       mf->addAtom(*veneer);
     }
@@ -416,20 +494,25 @@ protected:
   const ELFLinkingContext &_ctx;
 
   /// \brief Map Atoms to their GOT entries.
-  llvm::DenseMap<const Atom *, GOTAtom *> _gotMap;
+  llvm::MapVector<const Atom *, GOTAtom *> _gotAtoms;
 
-  /// \brief Map Atoms to their PLT entries.
-  llvm::DenseMap<const Atom *, PLTAtom *> _pltMap;
+  /// \brief Map Atoms to their PLT entries depending on the code model.
+  struct PLTWithVeneer {
+    PLTWithVeneer(PLTAtom *p = nullptr, PLTAtom *v = nullptr)
+        : _plt(p), _veneer(v) {}
+
+    bool empty() const {
+      assert((_plt || !_veneer) && "Veneer appears without PLT entry");
+      return !_plt && !_veneer;
+    }
+
+    PLTAtom *_plt;
+    PLTAtom *_veneer;
+  };
+  llvm::MapVector<const Atom *, PLTWithVeneer> _pltAtoms;
 
   /// \brief Map Atoms to their veneers.
-  llvm::DenseMap<const Atom *, VeneerAtom *> _veneerMap;
-
-  /// \brief the list of GOT/PLT atoms
-  std::vector<GOTAtom *> _gotVector;
-  std::vector<PLTAtom *> _pltVector;
-
-  /// \brief the list of veneer atoms.
-  std::vector<VeneerAtom *> _veneerVector;
+  llvm::MapVector<const Atom *, VeneerAtom *> _veneerAtoms;
 
   /// \brief GOT entry that is always 0. Used for undefined weaks.
   GOTAtom *_null = nullptr;
@@ -450,10 +533,8 @@ public:
   /// \brief Get the veneer for ARM B/BL instructions.
   const VeneerAtom *getVeneer_ARM_B_BL(const DefinedAtom *da,
                                        StringRef secName) {
-    auto veneer = _veneerMap.find(da);
-    if (_veneerMap.end() != veneer)
-      return veneer->second;
-
+    if (auto veneer = _veneerAtoms.lookup(da))
+      return veneer;
     auto v = new (_file._alloc) Veneer_ARM_B_BL_StaticAtom(_file, secName);
     v->addReferenceELF_ARM(R_ARM_ABS32, 4, da, 0);
 
@@ -461,18 +542,15 @@ public:
     v->_name += da->name();
     v->_name += "_from_arm";
 
-    _veneerMap[da] = v;
-    _veneerVector.push_back(v);
+    _veneerAtoms[da] = v;
     return v;
   }
 
   /// \brief Get the veneer for Thumb B/BL instructions.
   const VeneerAtom *getVeneer_THM_B_BL(const DefinedAtom *da,
                                        StringRef secName) {
-    auto veneer = _veneerMap.find(da);
-    if (_veneerMap.end() != veneer)
-      return veneer->second;
-
+    if (auto veneer = _veneerAtoms.lookup(da))
+      return veneer;
     auto v = new (_file._alloc) Veneer_THM_B_BL_StaticAtom(_file, secName);
     v->addReferenceELF_ARM(R_ARM_JUMP24, 4, da, 0);
 
@@ -480,8 +558,7 @@ public:
     v->_name += da->name();
     v->_name += "_from_thumb";
 
-    _veneerMap[da] = v;
-    _veneerVector.push_back(v);
+    _veneerAtoms[da] = v;
     return v;
   }
 

Added: lld/trunk/test/elf/ARM/plt-interwork.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/ARM/plt-interwork.test?rev=233900&view=auto
==============================================================================
--- lld/trunk/test/elf/ARM/plt-interwork.test (added)
+++ lld/trunk/test/elf/ARM/plt-interwork.test Thu Apr  2 02:23:11 2015
@@ -0,0 +1,340 @@
+# Check that PLT entries are properly generated for cases when
+# referenced from both ARM and Thumb code.
+#
+# 1. ARM code generates PLT without transition veneer.
+# RUN: yaml2obj -format=elf -docnum 1 %s > %t-f1-arm.o
+# RUN: lld -flavor gnu -target arm-linux-gnu \
+# RUN: -Bstatic --noinhibit-exec %t-f1-arm.o -o %t
+# RUN: llvm-objdump -s %t | FileCheck -check-prefix=ARM-ONE %s
+
+# ARM-ONE: Contents of section .plt:
+# ARM-ONE-NEXT: 40007c 00c68fe2 00ca8ce2 7cffbce5
+#                          ^ regular veneer ^
+# Next line shows that .plt section ends.
+# ARM-ONE-NEXT: Contents of section .text:
+
+# 2. Thumb code generates PLT with transition veneer.
+# RUN: yaml2obj -format=elf -docnum 2 %s > %t-f1-thm.o
+# RUN: lld -flavor gnu -target arm-linux-gnu \
+# RUN: -Bstatic --noinhibit-exec %t-f1-thm.o -o %t
+# RUN: llvm-objdump -s %t | FileCheck -check-prefix=THM-ONE %s
+
+# THM-ONE: Contents of section .plt:
+# THM-ONE-NEXT: 40007c 78470000 00c68fe2 00ca8ce2 78ffbce5
+#                   bx pc ^^        ^ regular veneer ^
+# Next line shows that .plt section ends.
+# THM-ONE-NEXT: Contents of section .text:
+
+# 3. ARM + Thumb code generate same single PLT with transition veneer.
+# RUN: yaml2obj -format=elf -docnum 1 %s > %t-f1-arm.o
+# RUN: yaml2obj -format=elf -docnum 3 %s > %t-f1-thm-for-arm.o
+# RUN: lld -flavor gnu -target arm-linux-gnu \
+# RUN: -Bstatic --noinhibit-exec %t-f1-arm.o %t-f1-thm-for-arm.o -o %t
+# RUN: llvm-objdump -s %t | FileCheck -check-prefix=THM-ONE %s
+
+# 4. Thumb + ARM code generate same single PLT with transition veneer.
+# RUN: yaml2obj -format=elf -docnum 3 %s > %t-f1-thm-for-arm.o
+# RUN: yaml2obj -format=elf -docnum 1 %s > %t-f1-arm.o
+# RUN: lld -flavor gnu -target arm-linux-gnu \
+# RUN: -Bstatic --noinhibit-exec %t-f1-thm-for-arm.o %t-f1-arm.o -o %t
+# RUN: llvm-objdump -s %t | FileCheck -check-prefix=THM-ONE %s
+
+# 5. ARM + ARM code generate two PLTs without transition veneers.
+# RUN: yaml2obj -format=elf -docnum 1 %s > %t-f1-arm.o
+# RUN: yaml2obj -format=elf -docnum 4 %s > %t-f2-arm.o
+# RUN: lld -flavor gnu -target arm-linux-gnu \
+# RUN: -Bstatic --noinhibit-exec %t-f1-arm.o %t-f2-arm.o -o %t
+# RUN: llvm-objdump -s %t | FileCheck -check-prefix=ARM-TWO %s
+
+# ARM-TWO: Contents of section .plt:
+# ARM-TWO-NEXT: 400084 00c68fe2 00ca8ce2 74ffbce5 00c68fe2
+#                         ^ regular veneer 1 ^        ^ --
+# ARM-TWO-NEXT: 400094 00ca8ce2 6cffbce5
+#             --- regular veneer 2 ^
+# Next line shows that .plt section ends.
+# ARM-TWO-NEXT: Contents of section .text:
+
+# 6. ARM + Thumb code generate two PLTs without and with transition veneer.
+# RUN: yaml2obj -format=elf -docnum 1 %s > %t-f1-arm.o
+# RUN: yaml2obj -format=elf -docnum 5 %s > %t-f2-thm.o
+# RUN: lld -flavor gnu -target arm-linux-gnu \
+# RUN: -Bstatic --noinhibit-exec %t-f1-arm.o %t-f2-thm.o -o %t
+# RUN: llvm-objdump -s %t | FileCheck -check-prefix=ARM-THM-TWO %s
+
+# ARM-THM-TWO: Contents of section .plt:
+# ARM-THM-TWO-NEXT: 400084 00c68fe2 00ca8ce2 74ffbce5 78470000
+#                             ^ regular veneer 1 ^       ^^ bx pc 2
+# ARM-THM-TWO-NEXT: 400094 00c68fe2 00ca8ce2 68ffbce5
+#                             ^ regular veneer 2 ^
+# Next line shows that .plt section ends.
+# ARM-THM-TWO-NEXT: Contents of section .text:
+
+# 7. Thumb + ARM code generate two PLTs with and without transition veneer.
+# RUN: yaml2obj -format=elf -docnum 2 %s > %t-f1-thm.o
+# RUN: yaml2obj -format=elf -docnum 4 %s > %t-f2-arm.o
+# RUN: lld -flavor gnu -target arm-linux-gnu \
+# RUN: -Bstatic --noinhibit-exec %t-f1-thm.o %t-f2-arm.o -o %t
+# RUN: llvm-objdump -s %t | FileCheck -check-prefix=THM-ARM-TWO %s
+
+# THM-ARM-TWO: Contents of section .plt:
+# THM-ARM-TWO-NEXT: 400084 78470000 00c68fe2 00ca8ce2 70ffbce
+#                     bx pc 1 ^^       ^ regular veneer 1 ^
+# THM-ARM-TWO-NEXT: 400094 00c68fe2 00ca8ce2 68ffbce5
+#                             ^ regular veneer 2 ^
+# Next line shows that .plt section ends.
+# THM-ARM-TWO-NEXT: Contents of section .text:
+
+# 8. Thumb + Thumb code generate two PLTs with transition veneers.
+# RUN: yaml2obj -format=elf -docnum 2 %s > %t-f1-thm.o
+# RUN: yaml2obj -format=elf -docnum 5 %s > %t-f2-thm.o
+# RUN: lld -flavor gnu -target arm-linux-gnu \
+# RUN: -Bstatic --noinhibit-exec %t-f1-thm.o %t-f2-thm.o -o %t
+# RUN: llvm-objdump -s %t | FileCheck -check-prefix=THM-TWO %s
+
+# THM-TWO: Contents of section .plt:
+# THM-TWO-NEXT: 400084 78470000 00c68fe2 00ca8ce2 70ffbce5
+#                 bx pc 1 ^^       ^ regular veneer 1 ^
+# THM-TWO-NEXT: 400094 78470000 00c68fe2 00ca8ce2 64ffbce5
+#                 bx pc 2 ^^       ^ regular veneer 2 ^
+# Next line shows that .plt section ends.
+# THM-TWO-NEXT: Contents of section .text:
+
+# f1-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:         04B02DE500B08DE2003000E3003040E30300A0E100D04BE204B09DE41EFF2FE100482DE904B08DE2FEFFFFEB0030A0E10300A0E10088BDE8
+  - Name:            .rel.text
+    Type:            SHT_REL
+    Link:            .symtab
+    AddressAlign:    0x0000000000000004
+    Info:            .text
+    Relocations:
+      - Offset:          0x0000000000000008
+        Symbol:          main
+        Type:            R_ARM_MOVW_ABS_NC
+      - Offset:          0x000000000000000C
+        Symbol:          main
+        Type:            R_ARM_MOVT_ABS
+      - Offset:          0x0000000000000028
+        Symbol:          f1
+        Type:            R_ARM_CALL
+  - 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:            f1
+      Type:            STT_GNU_IFUNC
+      Section:         .text
+    - Name:            main
+      Type:            STT_FUNC
+      Section:         .text
+      Value:           0x0000000000000020
+
+# f1-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:         80B400AF40F20003C0F200031846BD465DF8047B704700BF80B500AFFFF7FEFF0346184680BD00BF
+  - Name:            .rel.text
+    Type:            SHT_REL
+    Link:            .symtab
+    AddressAlign:    0x0000000000000004
+    Info:            .text
+    Relocations:
+      - Offset:          0x0000000000000004
+        Symbol:          main
+        Type:            R_ARM_THM_MOVW_ABS_NC
+      - Offset:          0x0000000000000008
+        Symbol:          main
+        Type:            R_ARM_THM_MOVT_ABS
+      - Offset:          0x000000000000001C
+        Symbol:          f1
+        Type:            R_ARM_THM_CALL
+  - 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:            f1
+      Type:            STT_GNU_IFUNC
+      Section:         .text
+      Value:           0x0000000000000001
+    - Name:            main
+      Type:            STT_FUNC
+      Section:         .text
+      Value:           0x0000000000000019
+
+# f1-thm-for-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:         80B500AFFFF7FEFF0346184680BD00BF
+  - Name:            .rel.text
+    Type:            SHT_REL
+    Link:            .symtab
+    AddressAlign:    0x0000000000000004
+    Info:            .text
+    Relocations:
+      - Offset:          0x0000000000000004
+        Symbol:          f1
+        Type:            R_ARM_THM_CALL
+  - 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:            f
+      Type:            STT_FUNC
+      Section:         .text
+      Value:           0x0000000000000001
+    - Name:            f1
+
+# f2-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:         04B02DE500B08DE2003000E3003040E30300A0E100D04BE204B09DE41EFF2FE100482DE904B08DE2FEFFFFEB0030A0E10300A0E10088BDE8
+  - Name:            .rel.text
+    Type:            SHT_REL
+    Link:            .symtab
+    AddressAlign:    0x0000000000000004
+    Info:            .text
+    Relocations:
+      - Offset:          0x0000000000000008
+        Symbol:          f
+        Type:            R_ARM_MOVW_ABS_NC
+      - Offset:          0x000000000000000C
+        Symbol:          f
+        Type:            R_ARM_MOVT_ABS
+      - Offset:          0x0000000000000028
+        Symbol:          f2
+        Type:            R_ARM_CALL
+  - 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:            f2
+      Type:            STT_GNU_IFUNC
+      Section:         .text
+    - Name:            f
+      Type:            STT_FUNC
+      Section:         .text
+      Value:           0x0000000000000020
+
+# f2-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:         80B400AF40F20003C0F200031846BD465DF8047B704700BF80B500AFFFF7FEFF0346184680BD00BF
+  - Name:            .rel.text
+    Type:            SHT_REL
+    Link:            .symtab
+    AddressAlign:    0x0000000000000004
+    Info:            .text
+    Relocations:
+      - Offset:          0x0000000000000004
+        Symbol:          f
+        Type:            R_ARM_THM_MOVW_ABS_NC
+      - Offset:          0x0000000000000008
+        Symbol:          f
+        Type:            R_ARM_THM_MOVT_ABS
+      - Offset:          0x000000000000001C
+        Symbol:          f2
+        Type:            R_ARM_THM_CALL
+  - 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:            f2
+      Type:            STT_GNU_IFUNC
+      Section:         .text
+      Value:           0x0000000000000001
+    - Name:            f
+      Type:            STT_FUNC
+      Section:         .text
+      Value:           0x0000000000000019
+...

Modified: lld/trunk/test/elf/ARM/rel-ifunc.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/ARM/rel-ifunc.test?rev=233900&r1=233899&r2=233900&view=diff
==============================================================================
--- lld/trunk/test/elf/ARM/rel-ifunc.test (original)
+++ lld/trunk/test/elf/ARM/rel-ifunc.test Thu Apr  2 02:23:11 2015
@@ -7,14 +7,14 @@
 # CHECK: Contents of section .rel.plt:
 # CHECK: 400074 00104000
 # CHECK: Contents of section .plt:
-# CHECK: 400080 00c68fe2 00ca8ce2 78ffbce5
+# CHECK: 40007c 00c68fe2 00ca8ce2 7cffbce5
 # CHECK: Contents of section .text:
-# CHECK: 4001ac 00482de9 04b08de2 d4ffffeb b0ffffeb
+# CHECK: 4001a8 00482de9 04b08de2 d4ffffeb b0ffffeb
 #                                             ^ bl #-320 (to address 0x400080=__plt_ifunc_myfunc)
 # CHECK: Contents of section .got.plt:
-# CHECK: 401000 c4004000
+# CHECK: 401000 c0004000
 # CHECK: SYMBOL TABLE:
-# CHECK: 004000c4 g       .text	00000020 myfunc
+# CHECK: 004000c0 g       .text	00000020 myfunc
 # CHECK: 00400074 g       *ABS*	00000000 __rel_iplt_start
 # CHECK: 0040007c g       *ABS*	00000000 __rel_iplt_end
 





More information about the llvm-commits mailing list