[lld] r250555 - [ELF2] getLocalRelTarget should handle R_PPC64_TOC directly

Hal Finkel via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 16 14:55:41 PDT 2015


Author: hfinkel
Date: Fri Oct 16 16:55:40 2015
New Revision: 250555

URL: http://llvm.org/viewvc/llvm-project?rev=250555&view=rev
Log:
[ELF2] getLocalRelTarget should handle R_PPC64_TOC directly

R_PPC64_TOC does not have an associated symbol, but does have a non-zero VA
that target-specific code must compute using some non-trivial rule. We
handled this as a special case in PPC64TargetInfo::relocateOne, where
we knew to write this special address, but that did not work when creating shared
libraries. The special TOC address needs to be the subject of a
R_PPC64_RELATIVE relocation, and so we also need to know how to encode this
special address in the addend of that relocation.

Thus, some target-specific logic is necessary when creating R_PPC64_RELATIVE as
well. To solve this problem, we teach getLocalRelTarget to handle R_PPC64_TOC
as a special case. This allows us to remove the special case in
PPC64TargetInfo::relocateOne (simplifying code there), and naturally allows the
existing logic to do the right thing when creating associated R_PPC64_RELATIVE
relocations for shared libraries.

Added:
    lld/trunk/test/elf2/ppc64-shared-rel-toc.s
Modified:
    lld/trunk/ELF/InputSection.cpp
    lld/trunk/ELF/OutputSections.cpp
    lld/trunk/ELF/OutputSections.h
    lld/trunk/ELF/Target.cpp
    lld/trunk/ELF/Target.h

Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=250555&r1=250554&r2=250555&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Fri Oct 16 16:55:40 2015
@@ -57,7 +57,7 @@ void InputSection<ELFT>::relocate(
     // resolved so we don't allocate a SymbolBody.
     const Elf_Shdr *SymTab = File.getSymbolTable();
     if (SymIndex < SymTab->sh_info) {
-      uintX_t SymVA = getLocalRelTarget(File, RI);
+      uintX_t SymVA = getLocalRelTarget(File, RI, Type);
       relocateOne(Buf, BufEnd, RI, Type, BaseAddr, SymVA);
       continue;
     }

Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=250555&r1=250554&r2=250555&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Fri Oct 16 16:55:40 2015
@@ -126,7 +126,7 @@ template <class ELFT> void RelocationSec
         if (Body)
           Addend += getSymVA<ELFT>(cast<ELFSymbolBody<ELFT>>(*Body));
         else
-          Addend += getLocalRelTarget(File, RI);
+          Addend += getLocalRelTarget(File, RI, Type);
       }
       P->setSymbolAndType(0, Target->getRelativeReloc(), IsMips64EL);
     }
@@ -424,15 +424,19 @@ typename ELFFile<ELFT>::uintX_t lld::elf
 template <class ELFT>
 typename ELFFile<ELFT>::uintX_t
 lld::elf2::getLocalRelTarget(const ObjectFile<ELFT> &File,
-                             const typename ELFFile<ELFT>::Elf_Rel &RI) {
+                             const typename ELFFile<ELFT>::Elf_Rel &RI,
+                             uint32_t Type) {
+  // PPC64 has a special relocation representing the TOC base pointer
+  // that does not have a corresponding symbol.
+  if (Config->EMachine == EM_PPC64 && Type == R_PPC64_TOC)
+    return getPPC64TocBase();
+
   typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym;
   const Elf_Sym *Sym =
       File.getObj().getRelocationSymbol(&RI, File.getSymbolTable());
 
-  // For certain special relocations, such as R_PPC64_TOC, there's no
-  // corresponding symbol. Just return 0 in that case.
   if (!Sym)
-    return 0;
+    error("Unsupported relocation without symbol");
 
   // According to the ELF spec reference to a local symbol from outside
   // the group are not allowed. Unfortunately .eh_frame breaks that rule
@@ -743,19 +747,19 @@ template ELFFile<ELF64BE>::uintX_t getSy
 
 template ELFFile<ELF32LE>::uintX_t
 getLocalRelTarget(const ObjectFile<ELF32LE> &,
-                  const ELFFile<ELF32LE>::Elf_Rel &);
+                  const ELFFile<ELF32LE>::Elf_Rel &, uint32_t);
 
 template ELFFile<ELF32BE>::uintX_t
 getLocalRelTarget(const ObjectFile<ELF32BE> &,
-                  const ELFFile<ELF32BE>::Elf_Rel &);
+                  const ELFFile<ELF32BE>::Elf_Rel &, uint32_t);
 
 template ELFFile<ELF64LE>::uintX_t
 getLocalRelTarget(const ObjectFile<ELF64LE> &,
-                  const ELFFile<ELF64LE>::Elf_Rel &);
+                  const ELFFile<ELF64LE>::Elf_Rel &, uint32_t);
 
 template ELFFile<ELF64BE>::uintX_t
 getLocalRelTarget(const ObjectFile<ELF64BE> &,
-                  const ELFFile<ELF64BE>::Elf_Rel &);
+                  const ELFFile<ELF64BE>::Elf_Rel &, uint32_t);
 
 template bool includeInSymtab<ELF32LE>(const SymbolBody &);
 template bool includeInSymtab<ELF32BE>(const SymbolBody &);

Modified: lld/trunk/ELF/OutputSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.h?rev=250555&r1=250554&r2=250555&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.h (original)
+++ lld/trunk/ELF/OutputSections.h Fri Oct 16 16:55:40 2015
@@ -38,7 +38,8 @@ typename llvm::object::ELFFile<ELFT>::ui
 template <class ELFT>
 typename llvm::object::ELFFile<ELFT>::uintX_t
 getLocalRelTarget(const ObjectFile<ELFT> &File,
-                  const typename llvm::object::ELFFile<ELFT>::Elf_Rel &Sym);
+                  const typename llvm::object::ELFFile<ELFT>::Elf_Rel &Sym,
+                  uint32_t Type);
 bool canBePreempted(const SymbolBody *Body, bool NeedsGot);
 template <class ELFT> bool includeInSymtab(const SymbolBody &B);
 

Modified: lld/trunk/ELF/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=250555&r1=250554&r2=250555&view=diff
==============================================================================
--- lld/trunk/ELF/Target.cpp (original)
+++ lld/trunk/ELF/Target.cpp Fri Oct 16 16:55:40 2015
@@ -345,7 +345,7 @@ PPC64TargetInfo::PPC64TargetInfo() {
   VAStart = 0x10000000;
 }
 
-static uint64_t getPPC64TocBase() {
+uint64_t getPPC64TocBase() {
   // The TOC consists of sections .got, .toc, .tocbss, .plt in that
   // order. The TOC starts where the first of these sections starts.
 
@@ -426,11 +426,6 @@ void PPC64TargetInfo::relocateOne(uint8_
   uint64_t P = BaseAddr + Rel.r_offset;
   uint64_t TB = getPPC64TocBase();
 
-  if (Type == R_PPC64_TOC) {
-    write64be(L, TB);
-    return;
-  }
-
   // For a TOC-relative relocation, adjust the addend and proceed in terms of
   // the corresponding ADDR16 relocation type.
   switch (Type) {
@@ -536,6 +531,7 @@ void PPC64TargetInfo::relocateOne(uint8_
     write64be(L, SA - P);
     break;
   case R_PPC64_ADDR64:
+  case R_PPC64_TOC:
     write64be(L, SA);
     break;
   default:

Modified: lld/trunk/ELF/Target.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.h?rev=250555&r1=250554&r2=250555&view=diff
==============================================================================
--- lld/trunk/ELF/Target.h (original)
+++ lld/trunk/ELF/Target.h Fri Oct 16 16:55:40 2015
@@ -58,6 +58,8 @@ protected:
   unsigned PltEntrySize = 8;
 };
 
+uint64_t getPPC64TocBase();
+
 extern std::unique_ptr<TargetInfo> Target;
 TargetInfo *createTarget();
 }

Added: lld/trunk/test/elf2/ppc64-shared-rel-toc.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/ppc64-shared-rel-toc.s?rev=250555&view=auto
==============================================================================
--- lld/trunk/test/elf2/ppc64-shared-rel-toc.s (added)
+++ lld/trunk/test/elf2/ppc64-shared-rel-toc.s Fri Oct 16 16:55:40 2015
@@ -0,0 +1,27 @@
+// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
+// RUN: ld.lld2 -shared %t.o -o %t.so
+// RUN: llvm-readobj -t -r -dyn-symbols %t.so | FileCheck %s
+// REQUIRES: ppc
+
+// When we create the TOC reference in the shared library, make sure that the
+// R_PPC64_RELATIVE relocation uses the correct (non-zero) offset.
+
+        .globl  foo
+        .align  2
+        .type   foo, at function
+        .section        .opd,"aw", at progbits
+foo:                                    # @foo
+        .align  3
+        .quad   .Lfunc_begin0
+        .quad   .TOC. at tocbase
+        .quad   0
+        .text
+.Lfunc_begin0:
+        blr
+
+// CHECK: 0x20090 R_PPC64_RELATIVE - 0x10000
+// CHECK: 0x20098 R_PPC64_RELATIVE - 0x8000
+
+// CHECK: Name: foo (20)
+// CHECK-NEXT: Value: 0x20090
+




More information about the llvm-commits mailing list