[lld] r289045 - [ELF] ifunc implementation using synthetic sections

Peter Smith via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 8 04:58:56 PST 2016


Author: psmith
Date: Thu Dec  8 06:58:55 2016
New Revision: 289045

URL: http://llvm.org/viewvc/llvm-project?rev=289045&view=rev
Log:
[ELF] ifunc implementation using synthetic sections

This change introduces new synthetic sections IpltSection, IgotPltSection
that represent the ifunc entries that would previously have been put in
the PltSection and the GotPltSection. The separation makes sure that
the R_*_IRELATIVE relocations are placed after the non R_*_IRELATIVE
relocations, which permits ifunc resolvers to know that the .got.plt
slots will be initialized prior to the resolver being called.

A secondary benefit is that for ARM we can move the IgotPltSection and its
dynamic relocations to the .got and .rel.dyn as the ARM glibc expects all
the R_*_IRELATIVE relocations to be in the .rel.dyn

Differential revision: https://reviews.llvm.org/D27406


Added:
    lld/trunk/test/ELF/Inputs/arm-shared.s   (with props)
    lld/trunk/test/ELF/Inputs/shared2-x86-64.s   (with props)
    lld/trunk/test/ELF/aarch64-gnu-ifunc-plt.s   (with props)
    lld/trunk/test/ELF/arm-gnu-ifunc-plt.s   (with props)
    lld/trunk/test/ELF/gnu-ifunc-plt.s   (with props)
    lld/trunk/test/ELF/gnu-ifunc-shared.s   (with props)
Modified:
    lld/trunk/ELF/Relocations.cpp
    lld/trunk/ELF/Symbols.cpp
    lld/trunk/ELF/Symbols.h
    lld/trunk/ELF/SyntheticSections.cpp
    lld/trunk/ELF/SyntheticSections.h
    lld/trunk/ELF/Writer.cpp
    lld/trunk/test/ELF/aarch64-gnu-ifunc.s
    lld/trunk/test/ELF/arm-gnu-ifunc.s
    lld/trunk/test/ELF/gnu-ifunc-i386.s
    lld/trunk/test/ELF/gnu-ifunc.s

Modified: lld/trunk/ELF/Relocations.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=289045&r1=289044&r2=289045&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.cpp (original)
+++ lld/trunk/ELF/Relocations.cpp Thu Dec  8 06:58:55 2016
@@ -719,18 +719,20 @@ static void scanRelocs(InputSectionBase<
     if (needsPlt(Expr)) {
       if (Body.isInPlt())
         continue;
-      In<ELFT>::Plt->addEntry(Body);
 
-      uint32_t Rel;
-      if (Body.isGnuIFunc() && !Preemptible)
-        Rel = Target->IRelativeRel;
-      else
-        Rel = Target->PltRel;
-
-      In<ELFT>::GotPlt->addEntry(Body);
-      In<ELFT>::RelaPlt->addReloc({Rel, In<ELFT>::GotPlt,
-                                   Body.getGotPltOffset<ELFT>(), !Preemptible,
-                                   &Body, 0});
+      if (Body.isGnuIFunc() && !Preemptible) {
+        In<ELFT>::Iplt->addEntry(Body);
+        In<ELFT>::IgotPlt->addEntry(Body);
+        In<ELFT>::RelaIplt->addReloc({Target->IRelativeRel, In<ELFT>::IgotPlt,
+                                      Body.getGotPltOffset<ELFT>(),
+                                      !Preemptible, &Body, 0});
+      } else {
+        In<ELFT>::Plt->addEntry(Body);
+        In<ELFT>::GotPlt->addEntry(Body);
+        In<ELFT>::RelaPlt->addReloc({Target->PltRel, In<ELFT>::GotPlt,
+                                     Body.getGotPltOffset<ELFT>(), !Preemptible,
+                                     &Body, 0});
+      }
       continue;
     }
 

Modified: lld/trunk/ELF/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.cpp?rev=289045&r1=289044&r2=289045&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.cpp (original)
+++ lld/trunk/ELF/Symbols.cpp Thu Dec  8 06:58:55 2016
@@ -95,8 +95,8 @@ static typename ELFT::uint getSymVA(cons
 SymbolBody::SymbolBody(Kind K, StringRefZ Name, bool IsLocal, uint8_t StOther,
                        uint8_t Type)
     : SymbolKind(K), NeedsCopyOrPltAddr(false), IsLocal(IsLocal),
-      IsInGlobalMipsGot(false), Is32BitMipsGot(false), Type(Type),
-      StOther(StOther), Name(Name) {}
+      IsInGlobalMipsGot(false), Is32BitMipsGot(false), IsInIplt(false),
+      IsInIgot(false), Type(Type), StOther(StOther), Name(Name) {}
 
 // Returns true if a symbol can be replaced at load-time by a symbol
 // with the same name defined in other ELF executable or DSO.
@@ -151,6 +151,8 @@ template <class ELFT> typename ELFT::uin
 }
 
 template <class ELFT> typename ELFT::uint SymbolBody::getGotPltVA() const {
+  if (this->IsInIgot)
+    return In<ELFT>::IgotPlt->getVA() + getGotPltOffset<ELFT>();
   return In<ELFT>::GotPlt->getVA() + getGotPltOffset<ELFT>();
 }
 
@@ -159,6 +161,8 @@ template <class ELFT> typename ELFT::uin
 }
 
 template <class ELFT> typename ELFT::uint SymbolBody::getPltVA() const {
+  if (this->IsInIplt)
+    return In<ELFT>::Iplt->getVA() + PltIndex * Target->PltEntrySize;
   return In<ELFT>::Plt->getVA() + Target->PltHeaderSize +
          PltIndex * Target->PltEntrySize;
 }

Modified: lld/trunk/ELF/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=289045&r1=289044&r2=289045&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.h (original)
+++ lld/trunk/ELF/Symbols.h Thu Dec  8 06:58:55 2016
@@ -117,6 +117,12 @@ public:
   // True if this symbol is referenced by 32-bit GOT relocations.
   unsigned Is32BitMipsGot : 1;
 
+  // True if this symbol is in the Iplt sub-section of the Plt.
+  unsigned IsInIplt : 1;
+
+  // True if this symbol is in the Igot sub-section of the .got.plt or .got.
+  unsigned IsInIgot : 1;
+
   // The following fields have the same meaning as the ELF symbol attributes.
   uint8_t Type;    // symbol type
   uint8_t StOther; // st_other field value

Modified: lld/trunk/ELF/SyntheticSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.cpp?rev=289045&r1=289044&r2=289045&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.cpp (original)
+++ lld/trunk/ELF/SyntheticSections.cpp Thu Dec  8 06:58:55 2016
@@ -707,6 +707,36 @@ template <class ELFT> void GotPltSection
   }
 }
 
+// On ARM the IgotPltSection is part of the GotSection, on other Targets it is
+// part of the .got.plt
+template <class ELFT>
+IgotPltSection<ELFT>::IgotPltSection()
+    : SyntheticSection<ELFT>(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS,
+                             Target->GotPltEntrySize,
+                             Config->EMachine == EM_ARM ? ".got" : ".got.plt") {
+}
+
+template <class ELFT> void IgotPltSection<ELFT>::addEntry(SymbolBody &Sym) {
+  Sym.IsInIgot = true;
+  Sym.GotPltIndex = Entries.size();
+  Entries.push_back(&Sym);
+}
+
+template <class ELFT> size_t IgotPltSection<ELFT>::getSize() const {
+  return Entries.size() * Target->GotPltEntrySize;
+}
+
+template <class ELFT> void IgotPltSection<ELFT>::writeTo(uint8_t *Buf) {
+  for (const SymbolBody *B : Entries) {
+    if (Config->EMachine == EM_ARM)
+      // On ARM we are actually part of the Got and not GotPlt.
+      write32le(Buf, B->getVA<ELFT>());
+    else
+      Target->writeGotPlt(Buf, *B);
+    Buf += sizeof(uintX_t);
+  }
+}
+
 template <class ELFT>
 StringTableSection<ELFT>::StringTableSection(StringRef Name, bool Dynamic)
     : SyntheticSection<ELFT>(Dynamic ? (uintX_t)SHF_ALLOC : 0, SHT_STRTAB, 1,
@@ -805,11 +835,10 @@ template <class ELFT> void DynamicSectio
     return; // Already finalized.
 
   this->Link = In<ELFT>::DynStrTab->OutSec->SectionIndex;
-
-  if (!In<ELFT>::RelaDyn->empty()) {
+  if (In<ELFT>::RelaDyn->OutSec->Size > 0) {
     bool IsRela = Config->Rela;
     add({IsRela ? DT_RELA : DT_REL, In<ELFT>::RelaDyn});
-    add({IsRela ? DT_RELASZ : DT_RELSZ, In<ELFT>::RelaDyn->getSize()});
+    add({IsRela ? DT_RELASZ : DT_RELSZ, In<ELFT>::RelaDyn->OutSec->Size});
     add({IsRela ? DT_RELAENT : DT_RELENT,
          uintX_t(IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel))});
 
@@ -822,9 +851,9 @@ template <class ELFT> void DynamicSectio
         add({IsRela ? DT_RELACOUNT : DT_RELCOUNT, NumRelativeRels});
     }
   }
-  if (!In<ELFT>::RelaPlt->empty()) {
+  if (In<ELFT>::RelaPlt->OutSec->Size > 0) {
     add({DT_JMPREL, In<ELFT>::RelaPlt});
-    add({DT_PLTRELSZ, In<ELFT>::RelaPlt->getSize()});
+    add({DT_PLTRELSZ, In<ELFT>::RelaPlt->OutSec->Size});
     add({Config->EMachine == EM_MIPS ? DT_MIPS_PLTGOT : DT_PLTGOT,
          In<ELFT>::GotPlt});
     add({DT_PLTREL, uint64_t(Config->Rela ? DT_RELA : DT_REL)});
@@ -1401,6 +1430,36 @@ template <class ELFT> size_t PltSection<
 }
 
 template <class ELFT>
+IpltSection<ELFT>::IpltSection()
+    : SyntheticSection<ELFT>(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 16,
+                             ".plt") {}
+
+template <class ELFT> void IpltSection<ELFT>::writeTo(uint8_t *Buf) {
+  // The IRelative relocations do not support lazy binding so no header is
+  // needed
+  size_t Off = 0;
+  for (auto &I : Entries) {
+    const SymbolBody *B = I.first;
+    unsigned RelOff = I.second + In<ELFT>::Plt->getSize();
+    uint64_t Got = B->getGotPltVA<ELFT>();
+    uint64_t Plt = this->getVA() + Off;
+    Target->writePlt(Buf + Off, Got, Plt, B->PltIndex, RelOff);
+    Off += Target->PltEntrySize;
+  }
+}
+
+template <class ELFT> void IpltSection<ELFT>::addEntry(SymbolBody &Sym) {
+  Sym.PltIndex = Entries.size();
+  Sym.IsInIplt = true;
+  unsigned RelOff = In<ELFT>::RelaIplt->getRelocOffset();
+  Entries.push_back(std::make_pair(&Sym, RelOff));
+}
+
+template <class ELFT> size_t IpltSection<ELFT>::getSize() const {
+  return Entries.size() * Target->PltEntrySize;
+}
+
+template <class ELFT>
 GdbIndexSection<ELFT>::GdbIndexSection()
     : SyntheticSection<ELFT>(0, SHT_PROGBITS, 1, ".gdb_index") {}
 
@@ -1750,6 +1809,11 @@ template class elf::GotPltSection<ELF32B
 template class elf::GotPltSection<ELF64LE>;
 template class elf::GotPltSection<ELF64BE>;
 
+template class elf::IgotPltSection<ELF32LE>;
+template class elf::IgotPltSection<ELF32BE>;
+template class elf::IgotPltSection<ELF64LE>;
+template class elf::IgotPltSection<ELF64BE>;
+
 template class elf::StringTableSection<ELF32LE>;
 template class elf::StringTableSection<ELF32BE>;
 template class elf::StringTableSection<ELF64LE>;
@@ -1785,6 +1849,11 @@ template class elf::PltSection<ELF32BE>;
 template class elf::PltSection<ELF64LE>;
 template class elf::PltSection<ELF64BE>;
 
+template class elf::IpltSection<ELF32LE>;
+template class elf::IpltSection<ELF32BE>;
+template class elf::IpltSection<ELF64LE>;
+template class elf::IpltSection<ELF64BE>;
+
 template class elf::GdbIndexSection<ELF32LE>;
 template class elf::GdbIndexSection<ELF32BE>;
 template class elf::GdbIndexSection<ELF64LE>;

Modified: lld/trunk/ELF/SyntheticSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.h?rev=289045&r1=289044&r2=289045&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.h (original)
+++ lld/trunk/ELF/SyntheticSections.h Thu Dec  8 06:58:55 2016
@@ -206,6 +206,25 @@ private:
   std::vector<const SymbolBody *> Entries;
 };
 
+// The IgotPltSection is a Got associated with the IpltSection for GNU Ifunc
+// Symbols that will be relocated by Target->IRelativeRel.
+// On most Targets the IgotPltSection will immediately follow the GotPltSection
+// on ARM the IgotPltSection will immediately follow the GotSection.
+template <class ELFT>
+class IgotPltSection final : public SyntheticSection<ELFT> {
+  typedef typename ELFT::uint uintX_t;
+
+public:
+  IgotPltSection();
+  void addEntry(SymbolBody &Sym);
+  size_t getSize() const override;
+  void writeTo(uint8_t *Buf) override;
+  bool empty() const override { return Entries.empty(); }
+
+private:
+  std::vector<const SymbolBody *> Entries;
+};
+
 template <class ELFT>
 class StringTableSection final : public SyntheticSection<ELFT> {
 public:
@@ -431,6 +450,21 @@ private:
   std::vector<std::pair<const SymbolBody *, unsigned>> Entries;
 };
 
+// The IpltSection is a variant of Plt for recording entries for GNU Ifunc
+// symbols that will be subject to a Target->IRelativeRel
+// The IpltSection immediately follows the Plt section in the Output Section
+template <class ELFT> class IpltSection final : public SyntheticSection<ELFT> {
+public:
+  IpltSection();
+  void writeTo(uint8_t *Buf) override;
+  size_t getSize() const override;
+  void addEntry(SymbolBody &Sym);
+  bool empty() const override { return Entries.empty(); }
+
+private:
+  std::vector<std::pair<const SymbolBody *, unsigned>> Entries;
+};
+
 template <class ELFT>
 class GdbIndexSection final : public SyntheticSection<ELFT> {
   typedef typename ELFT::uint uintX_t;
@@ -644,12 +678,15 @@ template <class ELFT> struct In {
   static GotSection<ELFT> *Got;
   static MipsGotSection<ELFT> *MipsGot;
   static GotPltSection<ELFT> *GotPlt;
+  static IgotPltSection<ELFT> *IgotPlt;
   static HashTableSection<ELFT> *HashTab;
   static InputSection<ELFT> *Interp;
   static MipsRldMapSection<ELFT> *MipsRldMap;
   static PltSection<ELFT> *Plt;
+  static IpltSection<ELFT> *Iplt;
   static RelocationSection<ELFT> *RelaDyn;
   static RelocationSection<ELFT> *RelaPlt;
+  static RelocationSection<ELFT> *RelaIplt;
   static StringTableSection<ELFT> *ShStrTab;
   static StringTableSection<ELFT> *StrTab;
   static SymbolTableSection<ELFT> *SymTab;
@@ -669,12 +706,15 @@ template <class ELFT> GnuHashTableSectio
 template <class ELFT> GotSection<ELFT> *In<ELFT>::Got;
 template <class ELFT> MipsGotSection<ELFT> *In<ELFT>::MipsGot;
 template <class ELFT> GotPltSection<ELFT> *In<ELFT>::GotPlt;
+template <class ELFT> IgotPltSection<ELFT> *In<ELFT>::IgotPlt;
 template <class ELFT> HashTableSection<ELFT> *In<ELFT>::HashTab;
 template <class ELFT> InputSection<ELFT> *In<ELFT>::Interp;
 template <class ELFT> MipsRldMapSection<ELFT> *In<ELFT>::MipsRldMap;
 template <class ELFT> PltSection<ELFT> *In<ELFT>::Plt;
+template <class ELFT> IpltSection<ELFT> *In<ELFT>::Iplt;
 template <class ELFT> RelocationSection<ELFT> *In<ELFT>::RelaDyn;
 template <class ELFT> RelocationSection<ELFT> *In<ELFT>::RelaPlt;
+template <class ELFT> RelocationSection<ELFT> *In<ELFT>::RelaIplt;
 template <class ELFT> StringTableSection<ELFT> *In<ELFT>::ShStrTab;
 template <class ELFT> StringTableSection<ELFT> *In<ELFT>::StrTab;
 template <class ELFT> SymbolTableSection<ELFT> *In<ELFT>::SymTab;

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=289045&r1=289044&r2=289045&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Thu Dec  8 06:58:55 2016
@@ -356,6 +356,8 @@ template <class ELFT> void Writer<ELFT>:
 
   In<ELFT>::GotPlt = make<GotPltSection<ELFT>>();
   Symtab<ELFT>::X->Sections.push_back(In<ELFT>::GotPlt);
+  In<ELFT>::IgotPlt = make<IgotPltSection<ELFT>>();
+  Symtab<ELFT>::X->Sections.push_back(In<ELFT>::IgotPlt);
 
   if (Config->GdbIndex) {
     In<ELFT>::GdbIndex = make<GdbIndexSection<ELFT>>();
@@ -368,8 +370,17 @@ template <class ELFT> void Writer<ELFT>:
       Config->Rela ? ".rela.plt" : ".rel.plt", false /*Sort*/);
   Symtab<ELFT>::X->Sections.push_back(In<ELFT>::RelaPlt);
 
+  // The RelaIplt immediately follows .rel.plt (.rel.dyn for ARM) to ensure
+  // that the IRelative relocations are processed last by the dynamic loader
+  In<ELFT>::RelaIplt = make<RelocationSection<ELFT>>(
+      (Config->EMachine == EM_ARM) ? ".rel.dyn" : In<ELFT>::RelaPlt->Name,
+      false /*Sort*/);
+  Symtab<ELFT>::X->Sections.push_back(In<ELFT>::RelaIplt);
+
   In<ELFT>::Plt = make<PltSection<ELFT>>();
   Symtab<ELFT>::X->Sections.push_back(In<ELFT>::Plt);
+  In<ELFT>::Iplt = make<IpltSection<ELFT>>();
+  Symtab<ELFT>::X->Sections.push_back(In<ELFT>::Iplt);
 
   if (Config->EhFrameHdr) {
     In<ELFT>::EhFrameHdr = make<EhFrameHeader<ELFT>>();
@@ -651,10 +662,10 @@ template <class ELFT> void Writer<ELFT>:
   if (In<ELFT>::DynSymTab)
     return;
   StringRef S = Config->Rela ? "__rela_iplt_start" : "__rel_iplt_start";
-  addOptionalRegular<ELFT>(S, In<ELFT>::RelaPlt, 0);
+  addOptionalRegular<ELFT>(S, In<ELFT>::RelaIplt, 0);
 
   S = Config->Rela ? "__rela_iplt_end" : "__rel_iplt_end";
-  addOptionalRegular<ELFT>(S, In<ELFT>::RelaPlt, -1);
+  addOptionalRegular<ELFT>(S, In<ELFT>::RelaIplt, -1);
 }
 
 // The linker is expected to define some symbols depending on
@@ -1036,11 +1047,13 @@ template <class ELFT> void Writer<ELFT>:
   // symbol table section (DynSymTab) must be the first one.
   finalizeSynthetic<ELFT>(
       {In<ELFT>::DynSymTab, In<ELFT>::GnuHashTab, In<ELFT>::HashTab,
-       In<ELFT>::SymTab, In<ELFT>::ShStrTab, In<ELFT>::StrTab, In<ELFT>::VerDef,
-       In<ELFT>::DynStrTab, In<ELFT>::GdbIndex, In<ELFT>::Got,
-       In<ELFT>::MipsGot, In<ELFT>::GotPlt, In<ELFT>::RelaDyn,
-       In<ELFT>::RelaPlt, In<ELFT>::Plt, In<ELFT>::EhFrameHdr, In<ELFT>::VerSym,
-       In<ELFT>::VerNeed, In<ELFT>::Dynamic});
+       In<ELFT>::SymTab,    In<ELFT>::ShStrTab,   In<ELFT>::StrTab,
+       In<ELFT>::VerDef,    In<ELFT>::DynStrTab,  In<ELFT>::GdbIndex,
+       In<ELFT>::Got,       In<ELFT>::MipsGot,    In<ELFT>::IgotPlt,
+       In<ELFT>::GotPlt,    In<ELFT>::RelaDyn,    In<ELFT>::RelaIplt,
+       In<ELFT>::RelaPlt,   In<ELFT>::Plt,        In<ELFT>::Iplt,
+       In<ELFT>::Plt,       In<ELFT>::EhFrameHdr, In<ELFT>::VerSym,
+       In<ELFT>::VerNeed,   In<ELFT>::Dynamic});
 }
 
 template <class ELFT> void Writer<ELFT>::addPredefinedSections() {

Added: lld/trunk/test/ELF/Inputs/arm-shared.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/arm-shared.s?rev=289045&view=auto
==============================================================================
--- lld/trunk/test/ELF/Inputs/arm-shared.s (added)
+++ lld/trunk/test/ELF/Inputs/arm-shared.s Thu Dec  8 06:58:55 2016
@@ -0,0 +1,8 @@
+.syntax unified
+.global bar2
+.type bar2, %function
+bar2:
+
+.global zed2
+.type zed2, %function
+zed2:

Propchange: lld/trunk/test/ELF/Inputs/arm-shared.s
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: lld/trunk/test/ELF/Inputs/arm-shared.s
------------------------------------------------------------------------------
    svn:keywords = Rev Date Author URL Id

Added: lld/trunk/test/ELF/Inputs/shared2-x86-64.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/shared2-x86-64.s?rev=289045&view=auto
==============================================================================
--- lld/trunk/test/ELF/Inputs/shared2-x86-64.s (added)
+++ lld/trunk/test/ELF/Inputs/shared2-x86-64.s Thu Dec  8 06:58:55 2016
@@ -0,0 +1,9 @@
+.global bar2
+.type bar2, @function
+bar2:
+ ret
+
+.global zed2
+.type  zed2, @function
+zed2:
+ ret

Propchange: lld/trunk/test/ELF/Inputs/shared2-x86-64.s
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: lld/trunk/test/ELF/Inputs/shared2-x86-64.s
------------------------------------------------------------------------------
    svn:keywords = Rev Date Author URL Id

Added: lld/trunk/test/ELF/aarch64-gnu-ifunc-plt.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/aarch64-gnu-ifunc-plt.s?rev=289045&view=auto
==============================================================================
--- lld/trunk/test/ELF/aarch64-gnu-ifunc-plt.s (added)
+++ lld/trunk/test/ELF/aarch64-gnu-ifunc-plt.s Thu Dec  8 06:58:55 2016
@@ -0,0 +1,85 @@
+// RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux-gnu %S/Inputs/shared2.s -o %t1.o
+// RUN: ld.lld %t1.o --shared -o %t.so
+// RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux-gnu %s -o %t.o
+// RUN: ld.lld %t.so %t.o -o %tout
+// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DISASM
+// RUN: llvm-objdump -s %tout | FileCheck %s --check-prefix=GOTPLT
+// RUN: llvm-readobj -r -dynamic-table %tout | FileCheck %s
+// REQUIRES: aarch64
+
+// Check that the IRELATIVE relocations are after the JUMP_SLOT in the plt
+// CHECK: Relocations [
+// CHECK-NEXT:   Section (4) .rela.plt {
+// CHECK:     0x40018 R_AARCH64_JUMP_SLOT bar2 0x0
+// CHECK-NEXT:     0x40020 R_AARCH64_JUMP_SLOT zed2 0x0
+// CHECK-NEXT:     0x40028 R_AARCH64_IRELATIVE - 0x20000
+// CHECK-NEXT:     0x40030 R_AARCH64_IRELATIVE - 0x20004
+// CHECK-NEXT:   }
+// CHECK-NEXT: ]
+
+// Check that .got.plt entries point back to PLT header
+// GOTPLT: Contents of section .got.plt:
+// GOTPLT-NEXT:  40000 00000000 00000000 00000000 00000000
+// GOTPLT-NEXT:  40010 00000000 00000000 20000200 00000000
+// GOTPLT-NEXT:  40020 20000200 00000000 20000200 00000000
+// GOTPLT-NEXT:  40030 20000200 00000000
+
+// Check that the PLTRELSZ tag includes the IRELATIVE relocations
+// CHECK: DynamicSection [
+// CHECK:   0x0000000000000002 PLTRELSZ             96 (bytes)
+
+// Check that a PLT header is written and the ifunc entries appear last
+// DISASM: Disassembly of section .text:
+// DISASM-NEXT: foo:
+// DISASM-NEXT:    20000:       c0 03 5f d6     ret
+// DISASM:      bar:
+// DISASM-NEXT:    20004:       c0 03 5f d6     ret
+// DISASM:      _start:
+// DISASM-NEXT:    20008:       16 00 00 94     bl      #88
+// DISASM-NEXT:    2000c:       19 00 00 94     bl      #100
+// DISASM-NEXT:    20010:       0c 00 00 94     bl      #48
+// DISASM-NEXT:    20014:       0f 00 00 94     bl      #60
+// DISASM-NEXT: Disassembly of section .plt:
+// DISASM-NEXT: .plt:
+// DISASM-NEXT:    20020:       f0 7b bf a9     stp     x16, x30, [sp, #-16]!
+// DISASM-NEXT:    20024:       10 01 00 90     adrp    x16, #131072
+// DISASM-NEXT:    20028:       11 0a 40 f9     ldr     x17, [x16, #16]
+// DISASM-NEXT:    2002c:       10 42 00 91     add     x16, x16, #16
+// DISASM-NEXT:    20030:       20 02 1f d6     br      x17
+// DISASM-NEXT:    20034:       1f 20 03 d5     nop
+// DISASM-NEXT:    20038:       1f 20 03 d5     nop
+// DISASM-NEXT:    2003c:       1f 20 03 d5     nop
+// DISASM-NEXT:    20040:       10 01 00 90     adrp    x16, #131072
+// DISASM-NEXT:    20044:       11 0e 40 f9     ldr     x17, [x16, #24]
+// DISASM-NEXT:    20048:       10 62 00 91     add     x16, x16, #24
+// DISASM-NEXT:    2004c:       20 02 1f d6     br      x17
+// DISASM-NEXT:    20050:       10 01 00 90     adrp    x16, #131072
+// DISASM-NEXT:    20054:       11 12 40 f9     ldr     x17, [x16, #32]
+// DISASM-NEXT:    20058:       10 82 00 91     add     x16, x16, #32
+// DISASM-NEXT:    2005c:       20 02 1f d6     br      x17
+// DISASM-NEXT:    20060:       10 01 00 90     adrp    x16, #131072
+// DISASM-NEXT:    20064:       11 16 40 f9     ldr     x17, [x16, #40]
+// DISASM-NEXT:    20068:       10 a2 00 91     add     x16, x16, #40
+// DISASM-NEXT:    2006c:       20 02 1f d6     br      x17
+// DISASM-NEXT:    20070:       10 01 00 90     adrp    x16, #131072
+// DISASM-NEXT:    20074:       11 1a 40 f9     ldr     x17, [x16, #48]
+// DISASM-NEXT:    20078:       10 c2 00 91     add     x16, x16, #48
+// DISASM-NEXT:    2007c:       20 02 1f d6     br      x17
+
+.text
+.type foo STT_GNU_IFUNC
+.globl foo
+foo:
+ ret
+
+.type bar STT_GNU_IFUNC
+.globl bar
+bar:
+ ret
+
+.globl _start
+_start:
+ bl foo
+ bl bar
+ bl bar2
+ bl zed2

Propchange: lld/trunk/test/ELF/aarch64-gnu-ifunc-plt.s
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: lld/trunk/test/ELF/aarch64-gnu-ifunc-plt.s
------------------------------------------------------------------------------
    svn:keywords = Rev Date Author URL Id

Modified: lld/trunk/test/ELF/aarch64-gnu-ifunc.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/aarch64-gnu-ifunc.s?rev=289045&r1=289044&r2=289045&view=diff
==============================================================================
--- lld/trunk/test/ELF/aarch64-gnu-ifunc.s (original)
+++ lld/trunk/test/ELF/aarch64-gnu-ifunc.s Thu Dec  8 06:58:55 2016
@@ -22,8 +22,8 @@
 // CHECK-NEXT: }
 // CHECK:      Relocations [
 // CHECK-NEXT:   Section ({{.*}}) .rela.plt {
-// CHECK-NEXT:     0x30018 R_AARCH64_IRELATIVE
-// CHECK-NEXT:     0x30020 R_AARCH64_IRELATIVE
+// CHECK-NEXT:     0x30000 R_AARCH64_IRELATIVE
+// CHECK-NEXT:     0x30008 R_AARCH64_IRELATIVE
 // CHECK-NEXT:   }
 // CHECK-NEXT: ]
 // CHECK:      Symbols [
@@ -98,34 +98,27 @@
 
 // 344 = 0x158
 // 392 = 0x188
-// DISASM:      Disassembly of section .text:
+
+// DISASM: Disassembly of section .text:
 // DISASM-NEXT: foo:
 // DISASM-NEXT:  20000: c0 03 5f d6 ret
-// DISASM:      bar:
+// DISASM: bar:
 // DISASM-NEXT:  20004: c0 03 5f d6 ret
 // DISASM:      _start:
-// DISASM-NEXT:  20008: 0e 00 00 94 bl #56
-// DISASM-NEXT:  2000c: 11 00 00 94 bl #68
-// DISASM-NEXT:  20010: 42 60 05 91 add x2, x2, #344
-// DISASM-NEXT:  20014: 42 20 06 91 add x2, x2, #392
+// DISASM-NEXT:  20008: 06 00 00 94 bl #24
+// DISASM-NEXT:  2000c: 09 00 00 94     bl      #36
+// DISASM-NEXT:  20010: 42 60 05 91     add     x2, x2, #344
+// DISASM-NEXT:  20014: 42 20 06 91     add     x2, x2, #392
 // DISASM-NEXT: Disassembly of section .plt:
 // DISASM-NEXT: .plt:
-// DISASM-NEXT:  20020: f0 7b bf a9 stp x16, x30, [sp, #-16]!
-// DISASM-NEXT:  20024: 90 00 00 90 adrp x16, #65536
-// DISASM-NEXT:  20028: 11 0a 40 f9 ldr x17, [x16, #16]
-// DISASM-NEXT:  2002c: 10 42 00 91 add x16, x16, #16
-// DISASM-NEXT:  20030: 20 02 1f d6 br x17
-// DISASM-NEXT:  20034: 1f 20 03 d5 nop
-// DISASM-NEXT:  20038: 1f 20 03 d5 nop
-// DISASM-NEXT:  2003c: 1f 20 03 d5 nop
-// DISASM-NEXT:  20040: 90 00 00 90 adrp x16, #65536
-// DISASM-NEXT:  20044: 11 0e 40 f9 ldr x17, [x16, #24]
-// DISASM-NEXT:  20048: 10 62 00 91 add x16, x16, #24
-// DISASM-NEXT:  2004c: 20 02 1f d6 br x17
-// DISASM-NEXT:  20050: 90 00 00 90 adrp x16, #65536
-// DISASM-NEXT:  20054: 11 12 40 f9 ldr x17, [x16, #32]
-// DISASM-NEXT:  20058: 10 82 00 91 add x16, x16, #32
-// DISASM-NEXT:  2005c: 20 02 1f d6 br x17
+// DISASM-NEXT:  20020: 90 00 00 90 adrp x16, #65536
+// DISASM-NEXT:  20024: 11 02 40 f9 ldr x17, [x16]
+// DISASM-NEXT:  20028: 10 02 00 91 add x16, x16, #0
+// DISASM-NEXT:  2002c: 20 02 1f d6 br x17
+// DISASM-NEXT:  20030: 90 00 00 90 adrp x16, #65536
+// DISASM-NEXT:  20034: 11 06 40 f9 ldr x17, [x16, #8]
+// DISASM-NEXT:  20038: 10 22 00 91 add x16, x16, #8
+// DISASM-NEXT:  2003c: 20 02 1f d6 br x17
 
 .text
 .type foo STT_GNU_IFUNC

Added: lld/trunk/test/ELF/arm-gnu-ifunc-plt.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-gnu-ifunc-plt.s?rev=289045&view=auto
==============================================================================
--- lld/trunk/test/ELF/arm-gnu-ifunc-plt.s (added)
+++ lld/trunk/test/ELF/arm-gnu-ifunc-plt.s Thu Dec  8 06:58:55 2016
@@ -0,0 +1,93 @@
+// RUN: llvm-mc -filetype=obj -triple=armv7a-linux-gnueabihf %S/Inputs/arm-shared.s -o %t1.o
+// RUN: ld.lld %t1.o --shared -o %t.so
+// RUN: llvm-mc -filetype=obj -triple=armv7a-linux-gnueabihf %s -o %t.o
+// RUN: ld.lld %t.so %t.o -o %tout
+// RUN: llvm-objdump -triple=armv7a-linux-gnueabihf -d %tout | FileCheck %s --check-prefix=DISASM
+// RUN: llvm-objdump -s %tout | FileCheck %s --check-prefix=GOTPLT
+// RUN: llvm-readobj -r -dynamic-table %tout | FileCheck %s
+// REQUIRES: arm
+
+// Check that the IRELATIVE relocations are last in the .got
+// CHECK: Relocations [
+// CHECK-NEXT:   Section (4) .rel.dyn {
+// CHECK-NEXT:     0x12078 R_ARM_GLOB_DAT bar2 0x0
+// CHECK-NEXT:     0x1207C R_ARM_GLOB_DAT zed2 0x0
+// CHECK-NEXT:     0x12080 R_ARM_IRELATIVE - 0x0
+// CHECK-NEXT:     0x12084 R_ARM_IRELATIVE - 0x0
+// CHECK-NEXT:   }
+// CHECK-NEXT:   Section (5) .rel.plt {
+// CHECK-NEXT:     0x1300C R_ARM_JUMP_SLOT bar2 0x0
+// CHECK-NEXT:     0x13010 R_ARM_JUMP_SLOT zed2 0x0
+// CHECK-NEXT:   }
+// CHECK-NEXT: ]
+
+// Check that the GOT entries refer back to the ifunc resolver
+// GOTPLT: Contents of section .got:
+// GOTPLT-NEXT:  12078 00000000 00000000 00100100 04100100
+// GOTPLT-NEXT: Contents of section .got.plt:
+// GOTPLT-NEXT:  13000 00000000 00000000 00000000 20100100
+// GOTPLT-NEXT:  13010 20100100
+
+// DISASM: Disassembly of section .text:
+// DISASM-NEXT: foo:
+// DISASM-NEXT:    11000:       1e ff 2f e1     bx      lr
+// DISASM: bar:
+// DISASM-NEXT:    11004:       1e ff 2f e1     bx      lr
+// DISASM:      _start:
+// DISASM-NEXT:    11008:       14 00 00 eb     bl      #80
+// DISASM-NEXT:    1100c:       17 00 00 eb     bl      #92
+// DISASM:         11010:       00 00 00 00     .word   0x00000000
+// DISASM-NEXT:    11014:       04 00 00 00     .word   0x00000004
+// DISASM:         11018:       05 00 00 eb     bl      #20
+// DISASM-NEXT:    1101c:       08 00 00 eb     bl      #32
+// DISASM-NEXT: Disassembly of section .plt:
+// DISASM-NEXT: .plt:
+// DISASM-NEXT:    11020:       04 e0 2d e5     str     lr, [sp, #-4]!
+// DISASM-NEXT:    11024:       04 e0 9f e5     ldr     lr, [pc, #4]
+// DISASM-NEXT:    11028:       0e e0 8f e0     add     lr, pc, lr
+// DISASM-NEXT:    1102c:       08 f0 be e5     ldr     pc, [lr, #8]!
+// DISASM-NEXT:    11030:       d0 1f 00 00
+// DISASM-NEXT:    11034:       04 c0 9f e5     ldr     r12, [pc, #4]
+// DISASM-NEXT:    11038:       0f c0 8c e0     add     r12, r12, pc
+// DISASM-NEXT:    1103c:       00 f0 9c e5     ldr     pc, [r12]
+// DISASM-NEXT:    11040:       cc 1f 00 00
+// DISASM-NEXT:    11044:       04 c0 9f e5     ldr     r12, [pc, #4]
+// DISASM-NEXT:    11048:       0f c0 8c e0     add     r12, r12, pc
+// DISASM-NEXT:    1104c:       00 f0 9c e5     ldr     pc, [r12]
+// DISASM-NEXT:    11050:       c0 1f 00 00
+// Alignment to 16 byte boundary not strictly necessary on ARM, but harmless
+// DISASM-NEXT:    11054:       00 00 00 00     andeq   r0, r0, r0
+// DISASM-NEXT:    11058:       00 00 00 00     andeq   r0, r0, r0
+// DISASM-NEXT:    1105c:       00 00 00 00     andeq   r0, r0, r0
+// DISASM-NEXT:    11060:       04 c0 9f e5     ldr     r12, [pc, #4]
+// DISASM-NEXT:    11064:       0f c0 8c e0     add     r12, r12, pc
+// DISASM-NEXT:    11068:       00 f0 9c e5     ldr     pc, [r12]
+// DISASM-NEXT:    1106c:       14 10 00 00
+// DISASM-NEXT:    11070:       04 c0 9f e5     ldr     r12, [pc, #4]
+// DISASM-NEXT:    11074:       0f c0 8c e0     add     r12, r12, pc
+// DISASM-NEXT:    11078:       00 f0 9c e5     ldr     pc, [r12]
+// DISASM-NEXT:    1107c:       08 10 00 00
+
+
+.syntax unified
+.text
+.type foo STT_GNU_IFUNC
+.globl foo
+foo:
+ bx lr
+
+.type bar STT_GNU_IFUNC
+.globl bar
+bar:
+ bx lr
+
+.globl _start
+_start:
+ bl foo
+ bl bar
+ // Create entries in the .got and .rel.dyn so that we don't just have
+ // IRELATIVE
+ .word bar2(got)
+ .word zed2(got)
+ bl bar2
+ bl zed2

Propchange: lld/trunk/test/ELF/arm-gnu-ifunc-plt.s
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: lld/trunk/test/ELF/arm-gnu-ifunc-plt.s
------------------------------------------------------------------------------
    svn:keywords = Rev Date Author URL Id

Modified: lld/trunk/test/ELF/arm-gnu-ifunc.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-gnu-ifunc.s?rev=289045&r1=289044&r2=289045&view=diff
==============================================================================
--- lld/trunk/test/ELF/arm-gnu-ifunc.s (original)
+++ lld/trunk/test/ELF/arm-gnu-ifunc.s Thu Dec  8 06:58:55 2016
@@ -24,51 +24,63 @@ _start:
  movw r0,:lower16:__rel_iplt_end
  movt r0,:upper16:__rel_iplt_end
 
-// CHECK:      Sections [
-// CHECK:       Section {
-// CHECK:       Index: 1
-// CHECK-NEXT:  Name: .rel.plt
-// CHECK-NEXT:  Type: SHT_REL
-// CHECK-NEXT:  Flags [
-// CHECK-NEXT:    SHF_ALLOC
-// CHECK-NEXT:  ]
-// CHECK-NEXT:  Address: [[REL:.*]]
-// CHECK-NEXT:  Offset:
-// CHECK-NEXT:   Size: 16
-// CHECK-NEXT:   Link:
-// CHECK-NEXT:   Info:
-// CHECK-NEXT:   AddressAlignment: 4
-// CHECK-NEXT:   EntrySize: 8
-// CHECK-NEXT:  }
-// CHECK: Relocations [
-// CHECK-NEXT:  Section (1) .rel.plt {
-// CHECK-NEXT:    0x1200C R_ARM_IRELATIVE
-// CHECK-NEXT:    0x12010 R_ARM_IRELATIVE
-// CHECK-NEXT:  }
-// CHECK-NEXT:]
-// CHECK:  Symbols [
-// CHECK:   Symbol {
-// CHECK:         Name: __rel_iplt_end
-// CHECK-NEXT:    Value: 0x100E4
-// CHECK-NEXT:    Size: 0
-// CHECK-NEXT:    Binding: Local
-// CHECK-NEXT:    Type: None
-// CHECK-NEXT:    Other [
-// CHECK-NEXT:      STV_HIDDEN
-// CHECK-NEXT:    ]
-// CHECK-NEXT:    Section: .rel.plt
-// CHECK-NEXT:  }
-// CHECK-NEXT:  Symbol {
-// CHECK-NEXT:    Name: __rel_iplt_start
-// CHECK-NEXT:    Value: 0x100D4
-// CHECK-NEXT:    Size: 0
-// CHECK-NEXT:    Binding: Local
-// CHECK-NEXT:    Type: None
-// CHECK-NEXT:    Other [
-// CHECK-NEXT:      STV_HIDDEN
-// CHECK-NEXT:    ]
-// CHECK-NEXT:    Section: .rel.plt
-// CHECK-NEXT:  }
+// CHECK: Sections [
+// CHECK:   Section {
+// CHECK:        Section {
+// CHECK:          Name: .rel.dyn
+// CHECK-NEXT:     Type: SHT_REL
+// CHECK-NEXT:     Flags [
+// CHECK-NEXT:       SHF_ALLOC
+// CHECK-NEXT:     ]
+// CHECK-NEXT:     Address: 0x100F4
+// CHECK-NEXT:     Offset: 0xF4
+// CHECK-NEXT:     Size: 16
+// CHECK:          Name: .plt
+// CHECK-NEXT:     Type: SHT_PROGBITS
+// CHECK-NEXT:     Flags [
+// CHECK-NEXT:       SHF_ALLOC
+// CHECK-NEXT:       SHF_EXECINSTR
+// CHECK-NEXT:     ]
+// CHECK-NEXT:     Address: 0x11020
+// CHECK-NEXT:     Offset: 0x1020
+// CHECK-NEXT:     Size: 32
+// CHECK:          Name: .got
+// CHECK-NEXT:     Type: SHT_PROGBITS
+// CHECK-NEXT:     Flags [
+// CHECK-NEXT:       SHF_ALLOC
+// CHECK-NEXT:       SHF_WRITE
+// CHECK-NEXT:     ]
+// CHECK-NEXT:     Address: 0x12000
+// CHECK-NEXT:     Offset: 0x2000
+// CHECK-NEXT:     Size: 8
+// CHECK:      Relocations [
+// CHECK-NEXT:   Section (1) .rel.dyn {
+// CHECK-NEXT:     0x12000 R_ARM_IRELATIVE
+// CHECK-NEXT:     0x12004 R_ARM_IRELATIVE
+// CHECK-NEXT:   }
+// CHECK-NEXT: ]
+// CHECK:        Symbol {
+// CHECK:          Name: __rel_iplt_end (6)
+// CHECK-NEXT:     Value: 0x10104
+// CHECK-NEXT:     Size: 0
+// CHECK-NEXT:     Binding: Local
+// CHECK-NEXT:     Type: None
+// CHECK-NEXT:     Other [
+// CHECK-NEXT:       STV_HIDDEN
+// CHECK-NEXT:     ]
+// CHECK-NEXT:     Section: .rel.dyn
+// CHECK-NEXT:   }
+// CHECK-NEXT:   Symbol {
+// CHECK-NEXT:     Name: __rel_iplt_start
+// CHECK-NEXT:     Value: 0x100F4
+// CHECK-NEXT:     Size: 0
+// CHECK-NEXT:     Binding: Local
+// CHECK-NEXT:     Type: None
+// CHECK-NEXT:     Other [
+// CHECK-NEXT:       STV_HIDDEN
+// CHECK-NEXT:     ]
+// CHECK-NEXT:     Section: .rel.dyn
+// CHECK-NEXT:   }
 // CHECK-NEXT:  Symbol {
 // CHECK-NEXT:    Name: _start
 // CHECK-NEXT:    Value: 0x11008
@@ -97,35 +109,29 @@ _start:
 // CHECK-NEXT:    Section: .text
 // CHECK-NEXT:  }
 
-// DISASM:      Disassembly of section .text:
+// DISASM: Disassembly of section .text:
 // DISASM-NEXT: foo:
-// DISASM-NEXT:   11000:       1e ff 2f e1     bx      lr
-// DISASM: bar:
-// DISASM-NEXT:   11004:       1e ff 2f e1     bx      lr
-// DISASM: _start:
-// DISASM-NEXT:   11008:       09 00 00 eb     bl      #36
-// DISASM-NEXT:   1100c:       0c 00 00 eb     bl      #48
-// DISASM-NEXT:   11010:       d4 00 00 e3     movw    r0, #212
-// DISASM-NEXT:   11014:       01 00 40 e3     movt    r0, #1
-// r0 = 212 + 1 * 65536 = 100D4 = __rel_iplt_start
-// DISASM-NEXT:   11018:       e4 00 00 e3     movw    r0, #228
-// DISASM-NEXT:   1101c:       01 00 40 e3     movt    r0, #1
-// r1 = 228 + 1 * 65536 = 100E4 = __rel_iplt_end
+// DISASM-NEXT:    11000:	1e ff 2f e1 	bx	lr
+// DISASM:      bar:
+// DISASM-NEXT:    11004:	1e ff 2f e1 	bx	lr
+// DISASM:       _start:
+// DISASM-NEXT:    11008:	04 00 00 eb 	bl	#16
+// DISASM-NEXT:    1100c:	07 00 00 eb 	bl	#28
+// 1 * 65536 + 244 = 0x100f4 __rel_iplt_start
+// DISASM-NEXT:    11010:	f4 00 00 e3 	movw	r0, #244
+// DISASM-NEXT:    11014:	01 00 40 e3 	movt	r0, #1
+// 1 * 65536 + 260 = 0x10104 __rel_iplt_end
+// DISASM-NEXT:    11018:	04 01 00 e3 	movw	r0, #260
+// DISASM-NEXT:    1101c:	01 00 40 e3 	movt	r0, #1
 // DISASM-NEXT: Disassembly of section .plt:
 // DISASM-NEXT: .plt:
-// DISASM-NEXT:   11020:       04 e0 2d e5     str     lr, [sp, #-4]!
-// DISASM-NEXT:   11024:       04 e0 9f e5     ldr     lr, [pc, #4]
-// DISASM-NEXT:   11028:       0e e0 8f e0     add     lr, pc, lr
-// DISASM-NEXT:   1102c:       08 f0 be e5     ldr     pc, [lr, #8]!
-// 0x0fd0 + 0x11028 + 0x8 = 0x12000
-// DISASM-NEXT:   11030:       d0 0f 00 00
-// DISASM-NEXT:   11034:       04 c0 9f e5     ldr     r12, [pc, #4]
-// DISASM-NEXT:   11038:       0f c0 8c e0     add     r12, r12, pc
-// DISASM-NEXT:   1103c:       00 f0 9c e5     ldr     pc, [r12]
-// 0x0fcc + 0x11038 + 0x8 = 0x1200C
-// DISASM-NEXT:   11040:       cc 0f 00 00
-// DISASM-NEXT:   11044:       04 c0 9f e5     ldr     r12, [pc, #4]
-// DISASM-NEXT:   11048:       0f c0 8c e0     add     r12, r12, pc
-// DISASM-NEXT:   1104c:       00 f0 9c e5     ldr     pc, [r12]
-// 0x0fc0 + 0x11048 + 0x8 = 0x12010
-// DISASM-NEXT:   11050:       c0 0f 00 00
+// DISASM-NEXT:    11020:	04 c0 9f e5 	ldr	r12, [pc, #4]
+// DISASM-NEXT:    11024:	0f c0 8c e0 	add	r12, r12, pc
+// 11024 + 8 + fd4 = 0x12000
+// DISASM-NEXT:    11028:	00 f0 9c e5 	ldr	pc, [r12]
+// DISASM-NEXT:    1102c:	d4 0f 00 00
+// DISASM-NEXT:    11030:	04 c0 9f e5 	ldr	r12, [pc, #4]
+// DISASM-NEXT:    11034:	0f c0 8c e0 	add	r12, r12, pc
+// 11034 + 8 + fc8 = 0x12004
+// DISASM-NEXT:    11038:	00 f0 9c e5 	ldr	pc, [r12]
+// DISASM-NEXT:    1103c:	c8 0f 00 00

Modified: lld/trunk/test/ELF/gnu-ifunc-i386.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/gnu-ifunc-i386.s?rev=289045&r1=289044&r2=289045&view=diff
==============================================================================
--- lld/trunk/test/ELF/gnu-ifunc-i386.s (original)
+++ lld/trunk/test/ELF/gnu-ifunc-i386.s Thu Dec  8 06:58:55 2016
@@ -22,8 +22,8 @@
 // CHECK-NEXT: }
 // CHECK:     Relocations [
 // CHECK-NEXT:   Section ({{.*}}) .rel.plt {
-// CHECK-NEXT:     0x1200C R_386_IRELATIVE
-// CHECK-NEXT:     0x12010 R_386_IRELATIVE
+// CHECK-NEXT:     0x12000 R_386_IRELATIVE
+// CHECK-NEXT:     0x12004 R_386_IRELATIVE
 // CHECK-NEXT:   }
 // CHECK-NEXT: ]
 
@@ -88,30 +88,24 @@
 // CHECK-NEXT: }
 // CHECK-NEXT:]
 
-// DISASM:      Disassembly of section .text:
+// DISASM: Disassembly of section .text:
 // DISASM-NEXT: foo:
-// DISASM-NEXT: 11000: c3 retl
-// DISASM:      bar:
-// DISASM-NEXT: 11001: c3 retl
+// DISASM-NEXT:    11000: c3 retl
+// DISASM: bar:
+// DISASM-NEXT:    11001: c3 retl
 // DISASM:      _start:
-// DISASM-NEXT:    11002: e8 29 00 00 00 calll 41
-// DISASM-NEXT:    11007: e8 34 00 00 00 calll 52
+// DISASM-NEXT:    11002: e8 19 00 00 00 calll 25
+// DISASM-NEXT:    11007: e8 24 00 00 00 calll 36
 // DISASM-NEXT:    1100c: ba d4 00 01 00 movl $65748, %edx
 // DISASM-NEXT:    11011: ba e4 00 01 00 movl $65764, %edx
 // DISASM-NEXT: Disassembly of section .plt:
 // DISASM-NEXT: .plt:
-// DISASM-NEXT:    11020: ff 35 04 20 01 00 pushl 73732
-// DISASM-NEXT:    11026: ff 25 08 20 01 00 jmpl *73736
-// DISASM-NEXT:    1102c: 90 nop
-// DISASM-NEXT:    1102d: 90 nop
-// DISASM-NEXT:    1102e: 90 nop
-// DISASM-NEXT:    1102f: 90 nop
-// DISASM-NEXT:    11030: ff 25 0c 20 01 00 jmpl *73740
-// DISASM-NEXT:    11036: 68 00 00 00 00    pushl $0
-// DISASM-NEXT:    1103b: e9 e0 ff ff ff    jmp -32 <.plt>
-// DISASM-NEXT:    11040: ff 25 10 20 01 00 jmpl *73744
-// DISASM-NEXT:    11046: 68 08 00 00 00    pushl $8
-// DISASM-NEXT:    1104b: e9 d0 ff ff ff    jmp -48 <.plt>
+// DISASM-NEXT:    11020: ff 25 00 20 01 00 jmpl *73728
+// DISASM-NEXT:    11026: 68 10 00 00 00 pushl $16
+// DISASM-NEXT:    1102b: e9 e0 ff ff ff jmp -32 <_start+0xE>
+// DISASM-NEXT:    11030: ff 25 04 20 01 00 jmpl *73732
+// DISASM-NEXT:    11036: 68 18 00 00 00 pushl $24
+// DISASM-NEXT:    1103b: e9 d0 ff ff ff jmp -48 <_start+0xE>
 
 .text
 .type foo STT_GNU_IFUNC

Added: lld/trunk/test/ELF/gnu-ifunc-plt.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/gnu-ifunc-plt.s?rev=289045&view=auto
==============================================================================
--- lld/trunk/test/ELF/gnu-ifunc-plt.s (added)
+++ lld/trunk/test/ELF/gnu-ifunc-plt.s Thu Dec  8 06:58:55 2016
@@ -0,0 +1,74 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/shared2-x86-64.s -o %t1.o
+// RUN: ld.lld %t1.o --shared -o %t.so
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+// RUN: ld.lld %t.so %t.o -o %tout
+// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DISASM
+// RUN: llvm-objdump -s %tout | FileCheck %s --check-prefix=GOTPLT
+// RUN: llvm-readobj -r -dynamic-table %tout | FileCheck %s
+// REQUIRES: x86
+
+// Check that the IRELATIVE relocations are after the JUMP_SLOT in the plt
+// CHECK: Relocations [
+// CHECK-NEXT:   Section (4) .rela.plt {
+// CHECK-NEXT:     0x203018 R_X86_64_JUMP_SLOT bar2 0x0
+// CHECK-NEXT:     0x203020 R_X86_64_JUMP_SLOT zed2 0x0
+// CHECK-NEXT:     0x203028 R_X86_64_IRELATIVE - 0x201000
+// CHECK-NEXT:     0x203030 R_X86_64_IRELATIVE - 0x201001
+
+// Check that .got.plt entries point back to PLT header
+// GOTPLT: Contents of section .got.plt:
+// GOTPLT-NEXT:  203000 00202000 00000000 00000000 00000000  .  .............
+// GOTPLT-NEXT:  203010 00000000 00000000 36102000 00000000  ........6. .....
+// GOTPLT-NEXT:  203020 46102000 00000000 56102000 00000000  F. .....V. .....
+// GOTPLT-NEXT:  203030 66102000 00000000
+
+// Check that the PLTRELSZ tag includes the IRELATIVE relocations
+// CHECK: DynamicSection [
+// CHECK:   0x0000000000000002 PLTRELSZ             96 (bytes)
+
+// Check that a PLT header is written and the ifunc entries appear last
+// DISASM: Disassembly of section .text:
+// DISASM-NEXT: foo:
+// DISASM-NEXT:   201000:       c3      retq
+// DISASM:      bar:
+// DISASM-NEXT:   201001:       c3      retq
+// DISASM:      _start:
+// DISASM-NEXT:   201002:       e8 49 00 00 00          callq   73
+// DISASM-NEXT:   201007:       e8 54 00 00 00          callq   84
+// DISASM-NEXT:   20100c:       e8 1f 00 00 00          callq   31
+// DISASM-NEXT:   201011:       e8 2a 00 00 00          callq   42
+// DISASM-NEXT: Disassembly of section .plt:
+// DISASM-NEXT: .plt:
+// DISASM-NEXT:   201020:       ff 35 e2 1f 00 00       pushq   8162(%rip)
+// DISASM-NEXT:   201026:       ff 25 e4 1f 00 00       jmpq    *8164(%rip)
+// DISASM-NEXT:   20102c:       0f 1f 40 00     nopl    (%rax)
+// DISASM-NEXT:   201030:       ff 25 e2 1f 00 00       jmpq    *8162(%rip)
+// DISASM-NEXT:   201036:       68 00 00 00 00          pushq   $0
+// DISASM-NEXT:   20103b:       e9 e0 ff ff ff          jmp     -32 <.plt>
+// DISASM-NEXT:   201040:       ff 25 da 1f 00 00       jmpq    *8154(%rip)
+// DISASM-NEXT:   201046:       68 01 00 00 00          pushq   $1
+// DISASM-NEXT:   20104b:       e9 d0 ff ff ff          jmp     -48 <.plt>
+// DISASM-NEXT:   201050:       ff 25 d2 1f 00 00       jmpq    *8146(%rip)
+// DISASM-NEXT:   201056:       68 00 00 00 00          pushq   $0
+// DISASM-NEXT:   20105b:       e9 e0 ff ff ff          jmp     -32 <.plt+0x20>
+// DISASM-NEXT:   201060:       ff 25 ca 1f 00 00       jmpq    *8138(%rip)
+// DISASM-NEXT:   201066:       68 01 00 00 00          pushq   $1
+// DISASM-NEXT:   20106b:       e9 d0 ff ff ff          jmp     -48 <.plt+0x20>
+
+.text
+.type foo STT_GNU_IFUNC
+.globl foo
+foo:
+ ret
+
+.type bar STT_GNU_IFUNC
+.globl bar
+bar:
+ ret
+
+.globl _start
+_start:
+ call foo
+ call bar
+ call bar2
+ call zed2

Propchange: lld/trunk/test/ELF/gnu-ifunc-plt.s
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: lld/trunk/test/ELF/gnu-ifunc-plt.s
------------------------------------------------------------------------------
    svn:keywords = Rev Date Author URL Id

Added: lld/trunk/test/ELF/gnu-ifunc-shared.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/gnu-ifunc-shared.s?rev=289045&view=auto
==============================================================================
--- lld/trunk/test/ELF/gnu-ifunc-shared.s (added)
+++ lld/trunk/test/ELF/gnu-ifunc-shared.s Thu Dec  8 06:58:55 2016
@@ -0,0 +1,66 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+// RUN: ld.lld --shared -o %t.so %t.o
+// RUN: llvm-objdump -d %t.so | FileCheck %s --check-prefix=DISASM
+// RUN: llvm-readobj -r %t.so | FileCheck %s
+
+// Check that an IRELATIVE relocation is used for a non-preemptible ifunc
+// handler and a JUMP_SLOT is used for a preemptible ifunc
+// DISASM: Disassembly of section .text:
+// DISASM-NEXT: fct:
+// DISASM-NEXT:     1000:       c3      retq
+// DISASM:     fct2:
+// DISASM-NEXT:     1001:       c3      retq
+// DISASM:     f1:
+// DISASM-NEXT:     1002:       e8 49 00 00 00          callq   73
+// DISASM-NEXT:     1007:       e8 24 00 00 00          callq   36
+// DISASM-NEXT:     100c:       e8 2f 00 00 00          callq   47
+// DISASM-NEXT:     1011:       c3      retq
+// DISASM:     f2:
+// DISASM-NEXT:     1012:       c3      retq
+// DISASM-NEXT: Disassembly of section .plt:
+// DISASM-NEXT: .plt:
+// DISASM-NEXT:     1020:       ff 35 e2 1f 00 00       pushq   8162(%rip)
+// DISASM-NEXT:     1026:       ff 25 e4 1f 00 00       jmpq    *8164(%rip)
+// DISASM-NEXT:     102c:       0f 1f 40 00     nopl    (%rax)
+// DISASM-NEXT:     1030:       ff 25 e2 1f 00 00       jmpq    *8162(%rip)
+// DISASM-NEXT:     1036:       68 00 00 00 00          pushq   $0
+// DISASM-NEXT:     103b:       e9 e0 ff ff ff          jmp     -32 <.plt>
+// DISASM-NEXT:     1040:       ff 25 da 1f 00 00       jmpq    *8154(%rip)
+// DISASM-NEXT:     1046:       68 01 00 00 00          pushq   $1
+// DISASM-NEXT:     104b:       e9 d0 ff ff ff          jmp     -48 <.plt>
+// DISASM-NEXT:     1050:       ff 25 d2 1f 00 00       jmpq    *8146(%rip)
+// DISASM-NEXT:     1056:       68 00 00 00 00          pushq   $0
+// DISASM-NEXT:     105b:       e9 e0 ff ff ff          jmp     -32 <.plt+0x20>
+
+// CHECK: Relocations [
+// CHECK-NEXT:   Section (4) .rela.plt {
+// CHECK-NEXT:     0x3018 R_X86_64_JUMP_SLOT fct2 0x0
+// CHECK-NEXT:     0x3020 R_X86_64_JUMP_SLOT f2 0x0
+// CHECK-NEXT:     0x3028 R_X86_64_IRELATIVE - 0x1000
+
+ // Hidden expect IRELATIVE
+ .globl fct
+ .hidden fct
+ .type  fct, STT_GNU_IFUNC
+fct:
+ ret
+
+ // Not hidden expect JUMP_SLOT
+ .globl fct2
+ .type  fct2, STT_GNU_IFUNC
+fct2:
+ ret
+
+ .globl f1
+ .type f1, @function
+f1:
+ call fct
+ call fct2
+ call f2 at PLT
+ ret
+
+ .globl f2
+ .type f2, @function
+f2:
+ ret

Propchange: lld/trunk/test/ELF/gnu-ifunc-shared.s
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: lld/trunk/test/ELF/gnu-ifunc-shared.s
------------------------------------------------------------------------------
    svn:keywords = Rev Date Author URL Id

Modified: lld/trunk/test/ELF/gnu-ifunc.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/gnu-ifunc.s?rev=289045&r1=289044&r2=289045&view=diff
==============================================================================
--- lld/trunk/test/ELF/gnu-ifunc.s (original)
+++ lld/trunk/test/ELF/gnu-ifunc.s Thu Dec  8 06:58:55 2016
@@ -22,8 +22,8 @@
 // CHECK-NEXT: }
 // CHECK:      Relocations [
 // CHECK-NEXT:   Section ({{.*}}) .rela.plt {
-// CHECK-NEXT:     0x202018 R_X86_64_IRELATIVE
-// CHECK-NEXT:     0x202020 R_X86_64_IRELATIVE
+// CHECK-NEXT:     0x202000 R_X86_64_IRELATIVE
+// CHECK-NEXT:     0x202008 R_X86_64_IRELATIVE
 // CHECK-NEXT:   }
 // CHECK-NEXT: ]
 // CHECK:      Symbols [
@@ -87,28 +87,25 @@
 // CHECK-NEXT:  }
 // CHECK-NEXT: ]
 
-// DISASM:      Disassembly of section .text:
+// DISASM: Disassembly of section .text:
 // DISASM-NEXT: foo:
-// DISASM-NEXT:   201000: {{.*}} retq
+// DISASM-NEXT:  201000: {{.*}} retq
 // DISASM:      bar:
-// DISASM-NEXT:   201001: {{.*}} retq
+// DISASM-NEXT:  201001: {{.*}} retq
 // DISASM:      _start:
-// DISASM-NEXT:   201002: {{.*}} callq 41
-// DISASM-NEXT:   201007: {{.*}} callq 52
-// DISASM-NEXT:   20100c: {{.*}} movl $2097496, %edx
-// DISASM-NEXT:   201011: {{.*}} movl $2097544, %edx
-// DISASM-NEXT:   201016: {{.*}} movl $2097545, %edx
+// DISASM-NEXT:  201002: {{.*}} callq 25
+// DISASM-NEXT:  201007: {{.*}} callq 36
+// DISASM-NEXT:  20100c: {{.*}} movl $2097496, %edx
+// DISASM-NEXT:  201011: {{.*}} movl $2097544, %edx
+// DISASM-NEXT:  201016: {{.*}} movl $2097545, %edx
 // DISASM-NEXT: Disassembly of section .plt:
 // DISASM-NEXT: .plt:
-// DISASM-NEXT:   201020: {{.*}} pushq 4066(%rip)
-// DISASM-NEXT:   201026: {{.*}} jmpq *4068(%rip)
-// DISASM-NEXT:   20102c: {{.*}} nopl (%rax)
-// DISASM-NEXT:   201030: {{.*}} jmpq *4066(%rip)
-// DISASM-NEXT:   201036: {{.*}} pushq $0
-// DISASM-NEXT:   20103b: {{.*}} jmp -32
-// DISASM-NEXT:   201040: {{.*}} jmpq *4058(%rip)
-// DISASM-NEXT:   201046: {{.*}} pushq $1
-// DISASM-NEXT:   20104b: {{.*}} jmp -48
+// DISASM-NEXT:  201020: {{.*}} jmpq *4058(%rip)
+// DISASM-NEXT:  201026: {{.*}} pushq $0
+// DISASM-NEXT:  20102b: {{.*}} jmp -32 <_start+0xE>
+// DISASM-NEXT:  201030: {{.*}} jmpq *4050(%rip)
+// DISASM-NEXT:  201036: {{.*}} pushq $1
+// DISASM-NEXT:  20103b: {{.*}} jmp -48 <_start+0xE>
 
 .text
 .type foo STT_GNU_IFUNC




More information about the llvm-commits mailing list