[lld] r256145 - [ELF] - fixed not properly handled @GOTTPOFF relocation against local symbols

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


Author: grimar
Date: Mon Dec 21 04:37:33 2015
New Revision: 256145

URL: http://llvm.org/viewvc/llvm-project?rev=256145&view=rev
Log:
[ELF] - fixed not properly handled @GOTTPOFF relocation against local symbols

This patch changes sequence of applying relocations, moving tls optimized relocation handling code before code for other locals.
Without that change relocation @GOTTPOFF against local symbol caused runtime error ("unrecognized reloc ...").
That change also should fix other tls optimized relocations, but I did not check them, that's a field for another patch.

R_X86_64_GOTTPOFF relocations against locals can be found when linking against libc.a(malloc.o):
000000000036 000600000016 R_X86_64_GOTTPOFF 0000000000000000 libc_tsd_MALLOC - 4
000000000131 000600000016 R_X86_64_GOTTPOFF 0000000000000000 libc_tsd_MALLOC - 4

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

Added:
    lld/trunk/test/ELF/tls-opt-local.s
Modified:
    lld/trunk/ELF/InputSection.cpp
    lld/trunk/ELF/OutputSections.cpp
    lld/trunk/ELF/OutputSections.h

Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=256145&r1=256144&r2=256145&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Mon Dec 21 04:37:33 2015
@@ -161,60 +161,66 @@ void InputSectionBase<ELFT>::relocate(ui
       continue;
     }
 
+    const Elf_Shdr *SymTab = File->getSymbolTable();
+    SymbolBody *Body = nullptr;
+    if (SymIndex >= SymTab->sh_info)
+      Body = File->getSymbolBody(SymIndex)->repl();
+
+    if (Target->isTlsOptimized(Type, Body)) {
+      uintX_t SymVA;
+      if (!Body)
+        SymVA = getLocalRelTarget(*File, RI, 0);
+      else if (Target->relocNeedsGot(Type, *Body))
+        SymVA = Out<ELFT>::Got->getEntryAddr(*Body);
+      else
+        SymVA = getSymVA<ELFT>(*Body);
+      // By optimizing TLS relocations, it is sometimes needed to skip
+      // relocations that immediately follow TLS relocations. This function
+      // knows how many slots we need to skip.
+      I += Target->relocateTlsOptimize(BufLoc, BufEnd, Type, AddrLoc, SymVA,
+                                       *Body);
+      continue;
+    }
+
     // Handle relocations for local symbols -- they never get
     // 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 A = getAddend<ELFT>(RI);
+    if (!Body) {
+      uintX_t SymVA = getLocalRelTarget(*File, RI, A);
       Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc, SymVA, 0,
                           findMipsPairedReloc(Buf, SymIndex, Type, NextRelocs));
       continue;
     }
 
-    SymbolBody &Body = *File->getSymbolBody(SymIndex)->repl();
-
     if (Target->isTlsGlobalDynamicReloc(Type) &&
-        !Target->isTlsOptimized(Type, &Body)) {
+        !Target->isTlsOptimized(Type, Body)) {
       Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc,
-                          Out<ELFT>::Got->getGlobalDynAddr(Body) +
+                          Out<ELFT>::Got->getGlobalDynAddr(*Body) +
                               getAddend<ELFT>(RI));
       continue;
     }
 
-    if (Target->isTlsOptimized(Type, &Body)) {
-      uintX_t SymVA = Target->relocNeedsGot(Type, Body)
-                          ? Out<ELFT>::Got->getEntryAddr(Body)
-                          : getSymVA<ELFT>(Body);
-      // By optimizing TLS relocations, it is sometimes needed to skip
-      // relocations that immediately follow TLS relocations. This function
-      // knows how many slots we need to skip.
-      I += Target->relocateTlsOptimize(BufLoc, BufEnd, Type, AddrLoc, SymVA,
-                                       Body);
-      continue;
-    }
-
-    uintX_t SymVA = getSymVA<ELFT>(Body);
-    if (Target->relocNeedsPlt(Type, Body)) {
-      SymVA = Out<ELFT>::Plt->getEntryAddr(Body);
+    uintX_t SymVA = getSymVA<ELFT>(*Body);
+    if (Target->relocNeedsPlt(Type, *Body)) {
+      SymVA = Out<ELFT>::Plt->getEntryAddr(*Body);
       Type = Target->getPltRefReloc(Type);
-    } else if (Target->relocNeedsGot(Type, Body)) {
-      SymVA = Out<ELFT>::Got->getEntryAddr(Body);
-      if (Body.isTls())
+    } else if (Target->relocNeedsGot(Type, *Body)) {
+      SymVA = Out<ELFT>::Got->getEntryAddr(*Body);
+      if (Body->isTls())
         Type = Target->getTlsGotReloc(Type);
-    } else if (!Target->needsCopyRel(Type, Body) &&
-               isa<SharedSymbol<ELFT>>(Body)) {
+    } else if (!Target->needsCopyRel(Type, *Body) &&
+               isa<SharedSymbol<ELFT>>(*Body)) {
       continue;
-    } else if (Target->isTlsDynReloc(Type, Body) ||
-               Target->isSizeDynReloc(Type, Body)) {
+    } else if (Target->isTlsDynReloc(Type, *Body) ||
+               Target->isSizeDynReloc(Type, *Body)) {
       continue;
     } else if (Config->EMachine == EM_MIPS) {
-      if (Type == R_MIPS_HI16 && &Body == Config->MipsGpDisp)
+      if (Type == R_MIPS_HI16 && Body == Config->MipsGpDisp)
         SymVA = getMipsGpAddr<ELFT>() - AddrLoc;
-      else if (Type == R_MIPS_LO16 && &Body == Config->MipsGpDisp)
+      else if (Type == R_MIPS_LO16 && Body == Config->MipsGpDisp)
         SymVA = getMipsGpAddr<ELFT>() - AddrLoc + 4;
     }
-    uintX_t A = getAddend<ELFT>(RI);
-    uintX_t Size = getSymSize<ELFT>(Body);
+    uintX_t Size = getSymSize<ELFT>(*Body);
     Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc, SymVA + A, Size + A,
                         findMipsPairedReloc(Buf, SymIndex, Type, NextRelocs));
   }

Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=256145&r1=256144&r2=256145&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Mon Dec 21 04:37:33 2015
@@ -307,9 +307,11 @@ template <class ELFT> void RelocationSec
     else if (Body)
       Addend = getSymVA<ELFT>(cast<ELFSymbolBody<ELFT>>(*Body)) + OrigAddend;
     else if (IsRela)
-      Addend = getLocalRelTarget(File, static_cast<const Elf_Rela &>(RI));
+      Addend =
+          getLocalRelTarget(File, static_cast<const Elf_Rela &>(RI),
+                            getAddend<ELFT>(static_cast<const Elf_Rela &>(RI)));
     else
-      Addend = getLocalRelTarget(File, RI);
+      Addend = getLocalRelTarget(File, RI, 0);
 
     if (IsRela)
       static_cast<Elf_Rela *>(P)->r_addend = Addend;
@@ -819,12 +821,11 @@ typename ELFFile<ELFT>::uintX_t lld::elf
 template <class ELFT, bool IsRela>
 typename ELFFile<ELFT>::uintX_t
 lld::elf2::getLocalRelTarget(const ObjectFile<ELFT> &File,
-                             const Elf_Rel_Impl<ELFT, IsRela> &RI) {
+                             const Elf_Rel_Impl<ELFT, IsRela> &RI,
+                             typename ELFFile<ELFT>::uintX_t Addend) {
   typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym;
   typedef typename ELFFile<ELFT>::uintX_t uintX_t;
 
-  uintX_t Addend = getAddend<ELFT>(RI);
-
   // PPC64 has a special relocation representing the TOC base pointer
   // that does not have a corresponding symbol.
   if (Config->EMachine == EM_PPC64 && RI.getType(false) == R_PPC64_TOC)
@@ -1500,29 +1501,20 @@ template ELFFile<ELF64BE>::uintX_t getSy
 
 template ELFFile<ELF32LE>::uintX_t
 getLocalRelTarget(const ObjectFile<ELF32LE> &,
-                  const ELFFile<ELF32LE>::Elf_Rel &);
-template ELFFile<ELF32BE>::uintX_t
-getLocalRelTarget(const ObjectFile<ELF32BE> &,
-                  const ELFFile<ELF32BE>::Elf_Rel &);
-template ELFFile<ELF64LE>::uintX_t
-getLocalRelTarget(const ObjectFile<ELF64LE> &,
-                  const ELFFile<ELF64LE>::Elf_Rel &);
-template ELFFile<ELF64BE>::uintX_t
-getLocalRelTarget(const ObjectFile<ELF64BE> &,
-                  const ELFFile<ELF64BE>::Elf_Rel &);
-
-template ELFFile<ELF32LE>::uintX_t
-getLocalRelTarget(const ObjectFile<ELF32LE> &,
-                  const ELFFile<ELF32LE>::Elf_Rela &);
+                  const ELFFile<ELF32LE>::Elf_Rel &,
+                  ELFFile<ELF32LE>::uintX_t Addend);
 template ELFFile<ELF32BE>::uintX_t
 getLocalRelTarget(const ObjectFile<ELF32BE> &,
-                  const ELFFile<ELF32BE>::Elf_Rela &);
+                  const ELFFile<ELF32BE>::Elf_Rel &,
+                  ELFFile<ELF32BE>::uintX_t Addend);
 template ELFFile<ELF64LE>::uintX_t
 getLocalRelTarget(const ObjectFile<ELF64LE> &,
-                  const ELFFile<ELF64LE>::Elf_Rela &);
+                  const ELFFile<ELF64LE>::Elf_Rel &,
+                  ELFFile<ELF64LE>::uintX_t Addend);
 template ELFFile<ELF64BE>::uintX_t
 getLocalRelTarget(const ObjectFile<ELF64BE> &,
-                  const ELFFile<ELF64BE>::Elf_Rela &);
+                  const ELFFile<ELF64BE>::Elf_Rel &,
+                  ELFFile<ELF64BE>::uintX_t Addend);
 
 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=256145&r1=256144&r2=256145&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.h (original)
+++ lld/trunk/ELF/OutputSections.h Mon Dec 21 04:37:33 2015
@@ -59,7 +59,8 @@ typename llvm::object::ELFFile<ELFT>::ui
 template <class ELFT, bool IsRela>
 typename llvm::object::ELFFile<ELFT>::uintX_t
 getLocalRelTarget(const ObjectFile<ELFT> &File,
-                  const llvm::object::Elf_Rel_Impl<ELFT, IsRela> &Rel);
+                  const llvm::object::Elf_Rel_Impl<ELFT, IsRela> &Rel,
+                  typename llvm::object::ELFFile<ELFT>::uintX_t Addend);
 bool canBePreempted(const SymbolBody *Body, bool NeedsGot);
 template <class ELFT> bool includeInSymtab(const SymbolBody &B);
 

Added: lld/trunk/test/ELF/tls-opt-local.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/tls-opt-local.s?rev=256145&view=auto
==============================================================================
--- lld/trunk/test/ELF/tls-opt-local.s (added)
+++ lld/trunk/test/ELF/tls-opt-local.s Mon Dec 21 04:37:33 2015
@@ -0,0 +1,52 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+// RUN: ld.lld %t.o -o %t1
+// RUN: llvm-readobj -r %t1 | FileCheck --check-prefix=NORELOC %s
+// RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASM %s
+
+// NORELOC:      Relocations [
+// NORELOC-NEXT: ]
+
+// DISASM:      Disassembly of section .text:
+// DISASM-NEXT: _start:
+// DISASM-NEXT: 11000: 48 c7 c0 f8 ff ff ff movq $-8, %rax
+// DISASM-NEXT: 11007: 49 c7 c7 f8 ff ff ff movq $-8, %r15
+// DISASM-NEXT: 1100e: 48 8d 80 f8 ff ff ff leaq -8(%rax), %rax
+// DISASM-NEXT: 11015: 4d 8d bf f8 ff ff ff leaq -8(%r15), %r15
+// DISASM-NEXT: 1101c: 48 81 c4 f8 ff ff ff addq $-8, %rsp
+// DISASM-NEXT: 11023: 49 81 c4 f8 ff ff ff addq $-8, %r12
+// DISASM-NEXT: 1102a: 48 c7 c0 fc ff ff ff movq $-4, %rax
+// DISASM-NEXT: 11031: 49 c7 c7 fc ff ff ff movq $-4, %r15
+// DISASM-NEXT: 11038: 48 8d 80 fc ff ff ff leaq -4(%rax), %rax
+// DISASM-NEXT: 1103f: 4d 8d bf fc ff ff ff leaq -4(%r15), %r15
+// DISASM-NEXT: 11046: 48 81 c4 fc ff ff ff addq $-4, %rsp
+// DISASM-NEXT: 1104d: 49 81 c4 fc ff ff ff addq $-4, %r12
+
+.section .tbss,"awT", at nobits
+
+.type tls0, at object
+.align 4
+tls0:
+ .long 0
+ .size tls0, 4
+
+.type  tls1, at object
+.align 4
+tls1:
+ .long 0
+ .size tls1, 4
+
+.section .text
+.globl _start
+_start:
+ movq tls0 at GOTTPOFF(%rip), %rax
+ movq tls0 at GOTTPOFF(%rip), %r15
+ addq tls0 at GOTTPOFF(%rip), %rax
+ addq tls0 at GOTTPOFF(%rip), %r15
+ addq tls0 at GOTTPOFF(%rip), %rsp
+ addq tls0 at GOTTPOFF(%rip), %r12
+ movq tls1 at GOTTPOFF(%rip), %rax
+ movq tls1 at GOTTPOFF(%rip), %r15
+ addq tls1 at GOTTPOFF(%rip), %rax
+ addq tls1 at GOTTPOFF(%rip), %r15
+ addq tls1 at GOTTPOFF(%rip), %rsp
+ addq tls1 at GOTTPOFF(%rip), %r12




More information about the llvm-commits mailing list