[lld] r256144 - [ELF] - Implemented R_*_IRELATIVE relocations for x86, x64 targets.

George Rimar via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 21 02:12:07 PST 2015


Author: grimar
Date: Mon Dec 21 04:12:06 2015
New Revision: 256144

URL: http://llvm.org/viewvc/llvm-project?rev=256144&view=rev
Log:
[ELF] - Implemented R_*_IRELATIVE relocations for x86, x64 targets.

This relocation is similar to R_*_RELATIVE except that the value used in this relocation is the program address returned by the function, which takes no arguments, at the address of
the result of the corresponding R_*_RELATIVE relocation as specified in the processor-specific ABI. The purpose of this relocation to avoid name lookup for locally defined STT_GNU_IFUNC symbols at load-time.

More info can be found in ifunc.txt from https://sites.google.com/site/x32abi/documents.

Differential revision: http://reviews.llvm.org/D15235

Added:
    lld/trunk/test/ELF/gnu-ifunc-i386.s
    lld/trunk/test/ELF/gnu-ifunc-nosym-i386.s
    lld/trunk/test/ELF/gnu-ifunc-nosym.s
    lld/trunk/test/ELF/gnu-ifunc.s
Modified:
    lld/trunk/ELF/OutputSections.cpp
    lld/trunk/ELF/OutputSections.h
    lld/trunk/ELF/Symbols.h
    lld/trunk/ELF/Target.cpp
    lld/trunk/ELF/Target.h
    lld/trunk/ELF/Writer.cpp

Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=256144&r1=256143&r2=256144&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Mon Dec 21 04:12:06 2015
@@ -269,7 +269,9 @@ template <class ELFT> void RelocationSec
 
     unsigned Sym = CanBePreempted ? Body->DynamicSymbolTableIndex : 0;
     unsigned Reloc;
-    if (!CanBePreempted || IsDynRelative)
+    if (!CanBePreempted && Body && isGnuIFunc<ELFT>(*Body))
+      Reloc = Target->getIRelativeReloc();
+    else if (!CanBePreempted || IsDynRelative)
       Reloc = Target->getRelativeReloc();
     else if (LazyReloc)
       Reloc = Target->getPltReloc();
@@ -320,7 +322,8 @@ template <class ELFT> unsigned Relocatio
 }
 
 template <class ELFT> void RelocationSection<ELFT>::finalize() {
-  this->Header.sh_link = Out<ELFT>::DynSymTab->SectionIndex;
+  this->Header.sh_link = Static ? Out<ELFT>::SymTab->SectionIndex
+                                : Out<ELFT>::DynSymTab->SectionIndex;
   this->Header.sh_size = Relocs.size() * this->Header.sh_entsize;
 }
 

Modified: lld/trunk/ELF/OutputSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.h?rev=256144&r1=256143&r2=256144&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.h (original)
+++ lld/trunk/ELF/OutputSections.h Mon Dec 21 04:12:06 2015
@@ -232,6 +232,8 @@ public:
   bool hasRelocs() const { return !Relocs.empty(); }
   bool isRela() const { return IsRela; }
 
+  bool Static = false;
+
 private:
   bool applyTlsDynamicReloc(SymbolBody *Body, uint32_t Type, Elf_Rel *P,
                             Elf_Rel *N);

Modified: lld/trunk/ELF/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=256144&r1=256143&r2=256144&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.h (original)
+++ lld/trunk/ELF/Symbols.h Mon Dec 21 04:12:06 2015
@@ -183,6 +183,11 @@ public:
   // The content for _gp symbol for MIPS target.
   static Elf_Sym MipsGp;
 
+  // __rel_iplt_start/__rel_iplt_end for signaling
+  // where R_[*]_IRELATIVE relocations do live.
+  static Elf_Sym RelaIpltStart;
+  static Elf_Sym RelaIpltEnd;
+
   DefinedAbsolute(StringRef N, const Elf_Sym &Sym)
       : Defined<ELFT>(Base::DefinedAbsoluteKind, N, Sym) {}
 
@@ -200,6 +205,12 @@ typename DefinedAbsolute<ELFT>::Elf_Sym
 template <class ELFT>
 typename DefinedAbsolute<ELFT>::Elf_Sym DefinedAbsolute<ELFT>::MipsGp;
 
+template <class ELFT>
+typename DefinedAbsolute<ELFT>::Elf_Sym DefinedAbsolute<ELFT>::RelaIpltStart;
+
+template <class ELFT>
+typename DefinedAbsolute<ELFT>::Elf_Sym DefinedAbsolute<ELFT>::RelaIpltEnd;
+
 template <class ELFT> class DefinedCommon : public Defined<ELFT> {
   typedef ELFSymbolBody<ELFT> Base;
   typedef typename Base::Elf_Sym Elf_Sym;

Modified: lld/trunk/ELF/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=256144&r1=256143&r2=256144&view=diff
==============================================================================
--- lld/trunk/ELF/Target.cpp (original)
+++ lld/trunk/ELF/Target.cpp Mon Dec 21 04:12:06 2015
@@ -70,6 +70,17 @@ template <unsigned N> static void checkA
   error("Improper alignment for relocation " + S);
 }
 
+template <class ELFT> bool isGnuIFunc(const SymbolBody &S) {
+  if (auto *SS = dyn_cast<Defined<ELFT>>(&S))
+    return SS->Sym.getType() == STT_GNU_IFUNC;
+  return false;
+}
+
+template bool isGnuIFunc<ELF32LE>(const SymbolBody &S);
+template bool isGnuIFunc<ELF32BE>(const SymbolBody &S);
+template bool isGnuIFunc<ELF64LE>(const SymbolBody &S);
+template bool isGnuIFunc<ELF64BE>(const SymbolBody &S);
+
 namespace {
 class X86TargetInfo final : public TargetInfo {
 public:
@@ -258,6 +269,7 @@ X86TargetInfo::X86TargetInfo() {
   PCRelReloc = R_386_PC32;
   GotReloc = R_386_GLOB_DAT;
   PltReloc = R_386_JUMP_SLOT;
+  IRelativeReloc = R_386_IRELATIVE;
   RelativeReloc = R_386_RELATIVE;
   TlsGotReloc = R_386_TLS_TPOFF;
   TlsGlobalDynamicReloc = R_386_TLS_GD;
@@ -357,7 +369,8 @@ bool X86TargetInfo::relocNeedsGot(uint32
 }
 
 bool X86TargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
-  return (Type == R_386_PLT32 && canBePreempted(&S, true)) ||
+  return isGnuIFunc<ELF32LE>(S) ||
+         (Type == R_386_PLT32 && canBePreempted(&S, true)) ||
          (Type == R_386_PC32 && S.isShared());
 }
 
@@ -557,6 +570,7 @@ X86_64TargetInfo::X86_64TargetInfo() {
   GotReloc = R_X86_64_GLOB_DAT;
   PltReloc = R_X86_64_JUMP_SLOT;
   RelativeReloc = R_X86_64_RELATIVE;
+  IRelativeReloc = R_X86_64_IRELATIVE;
   TlsGotReloc = R_X86_64_TPOFF64;
   TlsLocalDynamicReloc = R_X86_64_TLSLD;
   TlsGlobalDynamicReloc = R_X86_64_TLSGD;
@@ -633,6 +647,8 @@ unsigned X86_64TargetInfo::getPltRefRelo
 bool X86_64TargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
   if (needsCopyRel(Type, S))
     return false;
+  if (isGnuIFunc<ELF64LE>(S))
+    return true;
 
   switch (Type) {
   default:

Modified: lld/trunk/ELF/Target.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.h?rev=256144&r1=256143&r2=256144&view=diff
==============================================================================
--- lld/trunk/ELF/Target.h (original)
+++ lld/trunk/ELF/Target.h Mon Dec 21 04:12:06 2015
@@ -27,6 +27,7 @@ public:
   unsigned getGotReloc() const { return GotReloc; }
   unsigned getPltReloc() const { return PltReloc; }
   unsigned getRelativeReloc() const { return RelativeReloc; }
+  unsigned getIRelativeReloc() const { return IRelativeReloc; }
   bool isTlsLocalDynamicReloc(unsigned Type) const {
     return Type == TlsLocalDynamicReloc;
   }
@@ -88,6 +89,7 @@ protected:
   unsigned GotReloc;
   unsigned PltReloc;
   unsigned RelativeReloc;
+  unsigned IRelativeReloc;
   unsigned TlsGotReloc = 0;
   unsigned TlsLocalDynamicReloc = 0;
   unsigned TlsGlobalDynamicReloc = 0;
@@ -105,6 +107,8 @@ uint64_t getPPC64TocBase();
 template <class ELFT>
 typename llvm::object::ELFFile<ELFT>::uintX_t getMipsGpAddr();
 
+template <class ELFT> bool isGnuIFunc(const SymbolBody &S);
+
 extern std::unique_ptr<TargetInfo> Target;
 TargetInfo *createTarget();
 }

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=256144&r1=256143&r2=256144&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Mon Dec 21 04:12:06 2015
@@ -277,6 +277,15 @@ void Writer<ELFT>::scanRelocs(
       }
     }
 
+    // An STT_GNU_IFUNC symbol always uses a PLT entry, and all references
+    // to the symbol go through the PLT. This is true even for a local
+    // symbol, although local symbols normally do not require PLT entries.
+    if (Body && isGnuIFunc<ELFT>(*Body)) {
+      Body->setUsedInDynamicReloc();
+      Out<ELFT>::RelaPlt->addReloc({&C, &RI});
+      continue;
+    }
+
     if (Config->EMachine == EM_MIPS && NeedsGot) {
       // MIPS ABI has special rules to process GOT entries
       // and doesn't require relocation entries for them.
@@ -578,6 +587,27 @@ static bool compareSections(OutputSectio
   return std::distance(ItA, ItB) > 0;
 }
 
+// A statically linked executable will have rel[a].plt section
+// to hold R_[*]_IRELATIVE relocations.
+// The multi-arch libc will use these symbols to locate
+// these relocations at program startup time.
+// If RelaPlt is empty then there is no reason to create this symbols.
+template <class ELFT>
+static void addIRelocMarkers(SymbolTable<ELFT> &Symtab, bool IsDynamic) {
+  if (IsDynamic || !Out<ELFT>::RelaPlt || !Out<ELFT>::RelaPlt->hasRelocs())
+    return;
+  bool IsRela = shouldUseRela<ELFT>();
+  auto AddMarker = [&](StringRef Name, typename Writer<ELFT>::Elf_Sym &Sym) {
+    if (SymbolBody *B = Symtab.find(Name))
+      if (B->isUndefined())
+        Symtab.addAbsolute(Name, Sym);
+  };
+  AddMarker(IsRela ? "__rela_iplt_start" : "__rel_iplt_start",
+            DefinedAbsolute<ELFT>::RelaIpltStart);
+  AddMarker(IsRela ? "__rela_iplt_end" : "__rel_iplt_end",
+            DefinedAbsolute<ELFT>::RelaIpltEnd);
+}
+
 // Create output section objects and add them to OutputSections.
 template <class ELFT> void Writer<ELFT>::createSections() {
   // .interp needs to be on the first page in the output file.
@@ -720,6 +750,8 @@ template <class ELFT> void Writer<ELFT>:
     }
   }
 
+  addIRelocMarkers<ELFT>(Symtab, isOutputDynamic());
+
   std::vector<DefinedCommon<ELFT> *> CommonSymbols;
   std::vector<SharedSymbol<ELFT> *> SharedCopySymbols;
   for (auto &P : Symtab.getSymbols()) {
@@ -762,8 +794,6 @@ template <class ELFT> void Writer<ELFT>:
     OutputSections.push_back(Out<ELFT>::DynStrTab);
     if (Out<ELFT>::RelaDyn->hasRelocs())
       OutputSections.push_back(Out<ELFT>::RelaDyn);
-    if (Out<ELFT>::RelaPlt && Out<ELFT>::RelaPlt->hasRelocs())
-      OutputSections.push_back(Out<ELFT>::RelaPlt);
     // This is a MIPS specific section to hold a space within the data segment
     // of executable file which is pointed to by the DT_MIPS_RLD_MAP entry.
     // See "Dynamic section" in Chapter 5 in the following document:
@@ -777,6 +807,13 @@ template <class ELFT> void Writer<ELFT>:
     }
   }
 
+  // We always need to add rel[a].plt to output if it has entries.
+  // Even during static linking it can contain R_[*]_IRELATIVE relocations.
+  if (Out<ELFT>::RelaPlt && Out<ELFT>::RelaPlt->hasRelocs()) {
+    OutputSections.push_back(Out<ELFT>::RelaPlt);
+    Out<ELFT>::RelaPlt->Static = !isOutputDynamic();
+  }
+
   bool needsGot = !Out<ELFT>::Got->empty();
   // We add the .got section to the result for dynamic MIPS target because
   // its address and properties are mentioned in the .dynamic section.
@@ -997,6 +1034,15 @@ template <class ELFT> void Writer<ELFT>:
   // point to the end of the data segment.
   DefinedAbsolute<ELFT>::End.st_value = VA;
 
+  // Update __rel_iplt_start/__rel_iplt_end to wrap the
+  // rela.plt section.
+  if (Out<ELFT>::RelaPlt) {
+    uintX_t Start = Out<ELFT>::RelaPlt->getVA();
+    DefinedAbsolute<ELFT>::RelaIpltStart.st_value = Start;
+    DefinedAbsolute<ELFT>::RelaIpltEnd.st_value =
+        Start + Out<ELFT>::RelaPlt->getSize();
+  }
+
   // Update MIPS _gp absolute symbol so that it points to the static data.
   if (Config->EMachine == EM_MIPS)
     DefinedAbsolute<ELFT>::MipsGp.st_value = getMipsGpAddr<ELFT>();

Added: lld/trunk/test/ELF/gnu-ifunc-i386.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/gnu-ifunc-i386.s?rev=256144&view=auto
==============================================================================
--- lld/trunk/test/ELF/gnu-ifunc-i386.s (added)
+++ lld/trunk/test/ELF/gnu-ifunc-i386.s Mon Dec 21 04:12:06 2015
@@ -0,0 +1,130 @@
+// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o
+// RUN: ld.lld -static %t.o -o %tout
+// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DISASM
+// RUN: llvm-readobj -r -symbols -sections %tout | FileCheck %s --check-prefix=CHECK
+// REQUIRES: x86
+
+// 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: [[RELA:.*]]
+// CHECK-NEXT:  Offset: 0xD4
+// CHECK-NEXT:  Size: 16
+// CHECK-NEXT:  Link: 5
+// CHECK-NEXT:  Info: 0
+// CHECK-NEXT:  AddressAlignment: 4
+// CHECK-NEXT:  EntrySize: 8
+// CHECK-NEXT: }
+// CHECK:     Relocations [
+// CHECK-NEXT:   Section ({{.*}}) .rel.plt {
+// CHECK-NEXT:     0x1200C R_386_IRELATIVE
+// CHECK-NEXT:     0x12010 R_386_IRELATIVE
+// CHECK-NEXT:   }
+// CHECK-NEXT: ]
+
+// CHECK:      Symbols [
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT:   Name:
+// CHECK-NEXT:   Value: 0x0
+// CHECK-NEXT:   Size: 0
+// CHECK-NEXT:   Binding: Local
+// CHECK-NEXT:   Type: None
+// CHECK-NEXT:   Other: 0
+// CHECK-NEXT:   Section: Undefined
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT:   Name: __rel_iplt_end
+// CHECK-NEXT:   Value: 0x100E4
+// CHECK-NEXT:   Size: 0
+// CHECK-NEXT:   Binding: Local
+// CHECK-NEXT:   Type: None
+// CHECK-NEXT:   Other: 0
+// CHECK-NEXT:   Section: Absolute
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT:   Name: __rel_iplt_start
+// CHECK-NEXT:   Value: [[RELA]]
+// CHECK-NEXT:   Size: 0
+// CHECK-NEXT:   Binding: Local
+// CHECK-NEXT:   Type: None
+// CHECK-NEXT:   Other: 0
+// CHECK-NEXT:   Section: Absolute
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT:   Name: _start
+// CHECK-NEXT:   Value: 0x11002
+// CHECK-NEXT:   Size: 0
+// CHECK-NEXT:   Binding: Global
+// CHECK-NEXT:   Type: None
+// CHECK-NEXT:   Other: 0
+// CHECK-NEXT:   Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT:   Name: bar
+// CHECK-NEXT:   Value: 0x11001
+// CHECK-NEXT:   Size: 0
+// CHECK-NEXT:   Binding: Global
+// CHECK-NEXT:   Type: GNU_IFunc
+// CHECK-NEXT:   Other: 0
+// CHECK-NEXT:   Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT:   Name: foo
+// CHECK-NEXT:   Value: 0x11000
+// CHECK-NEXT:   Size: 0
+// CHECK-NEXT:   Binding: Global
+// CHECK-NEXT:   Type: GNU_IFunc
+// CHECK-NEXT:   Other: 0
+// CHECK-NEXT:   Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT:]
+
+// DISASM:      Disassembly of section .text:
+// DISASM-NEXT: foo:
+// 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:    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>
+
+.text
+.type foo STT_GNU_IFUNC
+.globl foo
+.type foo, @function
+foo:
+ ret
+
+.type bar STT_GNU_IFUNC
+.globl bar
+.type bar, @function
+bar:
+ ret
+
+.globl _start
+_start:
+ call foo
+ call bar
+ movl $__rel_iplt_start,%edx
+ movl $__rel_iplt_end,%edx

Added: lld/trunk/test/ELF/gnu-ifunc-nosym-i386.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/gnu-ifunc-nosym-i386.s?rev=256144&view=auto
==============================================================================
--- lld/trunk/test/ELF/gnu-ifunc-nosym-i386.s (added)
+++ lld/trunk/test/ELF/gnu-ifunc-nosym-i386.s Mon Dec 21 04:12:06 2015
@@ -0,0 +1,29 @@
+// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o
+// RUN: ld.lld -static %t.o -o %tout
+// RUN: llvm-readobj -symbols %tout | FileCheck %s
+// REQUIRES: x86
+
+// Check that no __rel_iplt_end/__rel_iplt_start
+// appear in symtab if there is no references to them.
+// CHECK:      Symbols [
+// CHECK-NEXT-NOT: __rel_iplt_end
+// CHECK-NEXT-NOT: __rel_iplt_start
+// CHECK: ]
+
+.text
+.type foo STT_GNU_IFUNC
+.globl foo
+.type foo, @function
+foo:
+ ret
+
+.type bar STT_GNU_IFUNC
+.globl bar
+.type bar, @function
+bar:
+ ret
+
+.globl _start
+_start:
+ call foo
+ call bar

Added: lld/trunk/test/ELF/gnu-ifunc-nosym.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/gnu-ifunc-nosym.s?rev=256144&view=auto
==============================================================================
--- lld/trunk/test/ELF/gnu-ifunc-nosym.s (added)
+++ lld/trunk/test/ELF/gnu-ifunc-nosym.s Mon Dec 21 04:12:06 2015
@@ -0,0 +1,29 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: ld.lld -static %t.o -o %tout
+// RUN: llvm-readobj -symbols %tout | FileCheck %s
+// REQUIRES: x86
+
+// Check that no __rela_iplt_end/__rela_iplt_start
+// appear in symtab if there is no references to them.
+// CHECK:      Symbols [
+// CHECK-NEXT-NOT: __rela_iplt_end
+// CHECK-NEXT-NOT: __rela_iplt_start
+// CHECK: ]
+
+.text
+.type foo STT_GNU_IFUNC
+.globl foo
+.type foo, @function
+foo:
+ ret
+
+.type bar STT_GNU_IFUNC
+.globl bar
+.type bar, @function
+bar:
+ ret
+
+.globl _start
+_start:
+ call foo
+ call bar

Added: lld/trunk/test/ELF/gnu-ifunc.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/gnu-ifunc.s?rev=256144&view=auto
==============================================================================
--- lld/trunk/test/ELF/gnu-ifunc.s (added)
+++ lld/trunk/test/ELF/gnu-ifunc.s Mon Dec 21 04:12:06 2015
@@ -0,0 +1,126 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: ld.lld -static %t.o -o %tout
+// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DISASM
+// RUN: llvm-readobj -r -symbols -sections %tout | FileCheck %s --check-prefix=CHECK
+// REQUIRES: x86
+
+// CHECK:      Sections [
+// CHECK:       Section {
+// CHECK:       Index: 1
+// CHECK-NEXT:  Name: .rela.plt
+// CHECK-NEXT:  Type: SHT_RELA
+// CHECK-NEXT:  Flags [
+// CHECK-NEXT:    SHF_ALLOC
+// CHECK-NEXT:  ]
+// CHECK-NEXT:  Address: [[RELA:.*]]
+// CHECK-NEXT:  Offset: 0x158
+// CHECK-NEXT:  Size: 48
+// CHECK-NEXT:  Link: 5
+// CHECK-NEXT:  Info: 0
+// CHECK-NEXT:  AddressAlignment: 8
+// CHECK-NEXT:  EntrySize: 24
+// CHECK-NEXT: }
+// CHECK:      Relocations [
+// CHECK-NEXT:   Section ({{.*}}) .rela.plt {
+// CHECK-NEXT:     0x12018 R_X86_64_IRELATIVE
+// CHECK-NEXT:     0x12020 R_X86_64_IRELATIVE
+// CHECK-NEXT:   }
+// CHECK-NEXT: ]
+// CHECK:      Symbols [
+// CHECK-NEXT:  Symbol {
+// CHECK-NEXT:    Name:
+// CHECK-NEXT:    Value: 0x0
+// CHECK-NEXT:    Size: 0
+// CHECK-NEXT:    Binding: Local
+// CHECK-NEXT:    Type: None
+// CHECK-NEXT:    Other: 0
+// CHECK-NEXT:    Section: Undefined
+// CHECK-NEXT:  }
+// CHECK-NEXT:  Symbol {
+// CHECK-NEXT:    Name: __rela_iplt_end
+// CHECK-NEXT:    Value: 0x10188
+// CHECK-NEXT:    Size: 0
+// CHECK-NEXT:    Binding: Local
+// CHECK-NEXT:    Type: None
+// CHECK-NEXT:    Other: 0
+// CHECK-NEXT:    Section: Absolute
+// CHECK-NEXT:  }
+// CHECK-NEXT:  Symbol {
+// CHECK-NEXT:    Name: __rela_iplt_start
+// CHECK-NEXT:    Value: [[RELA]]
+// CHECK-NEXT:    Size: 0
+// CHECK-NEXT:    Binding: Local
+// CHECK-NEXT:    Type: None
+// CHECK-NEXT:    Other: 0
+// CHECK-NEXT:    Section: Absolute
+// CHECK-NEXT:  }
+// CHECK-NEXT:  Symbol {
+// CHECK-NEXT:    Name: _start
+// CHECK-NEXT:    Value: 0x11002
+// CHECK-NEXT:    Size: 0
+// CHECK-NEXT:    Binding: Global
+// CHECK-NEXT:    Type: None
+// CHECK-NEXT:    Other: 0
+// CHECK-NEXT:    Section: .text
+// CHECK-NEXT:  }
+// CHECK-NEXT:  Symbol {
+// CHECK-NEXT:    Name: bar
+// CHECK-NEXT:    Value: 0x11001
+// CHECK-NEXT:    Size: 0
+// CHECK-NEXT:    Binding: Global
+// CHECK-NEXT:    Type: GNU_IFunc
+// CHECK-NEXT:    Other: 0
+// CHECK-NEXT:    Section: .text
+// CHECK-NEXT:  }
+// CHECK-NEXT:  Symbol {
+// CHECK-NEXT:    Name: foo
+// CHECK-NEXT:    Value: 0x11000
+// CHECK-NEXT:    Size: 0
+// CHECK-NEXT:    Binding: Global
+// CHECK-NEXT:    Type: GNU_IFunc
+// CHECK-NEXT:    Other: 0
+// CHECK-NEXT:    Section: .text
+// CHECK-NEXT:  }
+// CHECK-NEXT: ]
+
+// DISASM:      Disassembly of section .text:
+// DISASM-NEXT: foo:
+// DISASM-NEXT:    11000: c3 retq
+// DISASM:      bar:
+// DISASM-NEXT:    11001: c3 retq
+// DISASM:      _start:
+// DISASM-NEXT:    11002: e8 29 00 00 00 callq 41
+// DISASM-NEXT:    11007: e8 34 00 00 00 callq 52
+// DISASM-NEXT:    1100c: ba 58 01 01 00 movl $65880, %edx
+// DISASM-NEXT:    11011: ba 88 01 01 00 movl $65928, %edx
+// DISASM-NEXT: Disassembly of section .plt:
+// DISASM-NEXT: .plt:
+// DISASM-NEXT:    11020: ff 35 e2 0f 00 00 pushq 4066(%rip)
+// DISASM-NEXT:    11026: ff 25 e4 0f 00 00 jmpq *4068(%rip)
+// DISASM-NEXT:    1102c: 0f 1f 40 00       nopl (%rax)
+// DISASM-NEXT:    11030: ff 25 e2 0f 00 00 jmpq *4066(%rip)
+// DISASM-NEXT:    11036: 68 00 00 00 00    pushq $0
+// DISASM-NEXT:    1103b: e9 e0 ff ff ff    jmp -32
+// DISASM-NEXT:    11040: ff 25 da 0f 00 00 jmpq *4058(%rip)
+// DISASM-NEXT:    11046: 68 01 00 00 00    pushq $1
+// DISASM-NEXT:    1104b: e9 d0 ff ff ff    jmp -48
+
+.text
+.type foo STT_GNU_IFUNC
+.globl foo
+.type foo, @function
+foo:
+ ret
+
+.type bar STT_GNU_IFUNC
+.globl bar
+.type bar, @function
+bar:
+ ret
+
+.globl _start
+_start:
+ call foo
+ call bar
+ movl $__rela_iplt_start,%edx
+ movl $__rela_iplt_end,%edx




More information about the llvm-commits mailing list