Fix addend computation for IRELATIVE relocations.
authorRafael Espindola <rafael.espindola@gmail.com>
Wed, 3 Feb 2016 21:02:48 +0000 (21:02 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Wed, 3 Feb 2016 21:02:48 +0000 (21:02 +0000)
llvm-svn: 259692

lld/ELF/OutputSections.cpp
lld/test/ELF/gnu-ifunc-relative.s [new file with mode: 0644]

index 8f3ab01..391fe39 100644 (file)
@@ -285,6 +285,18 @@ template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) {
     bool NeedsGot = Body && Target->needsGot(Type, *Body);
     bool CBP = canBePreempted(Body, NeedsGot);
 
+    if (IsRela) {
+      auto R = static_cast<const Elf_Rela &>(RI);
+      auto S = static_cast<Elf_Rela *>(P);
+      uintX_t A = NeedsGot ? 0 : R.r_addend;
+      if (CBP)
+        S->r_addend = A;
+      else if (Body)
+        S->r_addend = Body->getVA<ELFT>() + A;
+      else
+        S->r_addend = getLocalRelTarget(File, R, A);
+    }
+
     // For a symbol with STT_GNU_IFUNC type, we always create a PLT and
     // a GOT entry for the symbol, and emit an IRELATIVE reloc rather than
     // the usual JUMP_SLOT reloc for the GOT entry. For the details, you
@@ -318,19 +330,6 @@ template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) {
       P->r_offset = Body->getGotVA<ELFT>();
     else
       P->r_offset = C.getOffset(RI.r_offset) + C.OutSec->getVA();
-
-    if (!IsRela)
-      continue;
-
-    auto R = static_cast<const Elf_Rela &>(RI);
-    auto S = static_cast<Elf_Rela *>(P);
-    uintX_t A = NeedsGot ? 0 : R.r_addend;
-    if (CBP)
-      S->r_addend = A;
-    else if (Body)
-      S->r_addend = Body->getVA<ELFT>() + A;
-    else
-      S->r_addend = getLocalRelTarget(File, R, A);
   }
 }
 
diff --git a/lld/test/ELF/gnu-ifunc-relative.s b/lld/test/ELF/gnu-ifunc-relative.s
new file mode 100644 (file)
index 0000000..94c76a8
--- /dev/null
@@ -0,0 +1,24 @@
+// 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 -r -t %tout | FileCheck %s
+// REQUIRES: x86
+
+.type foo STT_GNU_IFUNC
+.globl foo
+.type foo, @function
+foo:
+ ret
+
+.globl _start
+_start:
+ call foo
+
+// CHECK:      Section ({{.*}}) .rela.plt {
+// CHECK-NEXT:   R_X86_64_IRELATIVE - 0x[[ADDR:.*]]
+// CHECK-NEXT: }
+
+// CHECK:      Name: foo
+// CHECK-NEXT: Value: 0x[[ADDR]]
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: GNU_IFunc