Blob Blame History Raw
commit 14d96265dd8fd934d868c0b8e1991e2fefbe9fc8
Author: Will Newton <will.newton@linaro.org>
Date:   Mon Nov 25 14:44:59 2013 +0000

    bfd/elfnn-aarch64.c: Handle static links with ifunc correctly.
    
    The code for handling GOT references to ifunc symbols in static links
    was missing.
    
    bfd/ChangeLog:
    
    2013-11-26  Will Newton  <will.newton@linaro.org>
    
    	* elfnn-aarch64.c (elfNN_aarch64_finish_dynamic_symbol):
    	Handle STT_GNU_IFUNC symbols correctly in static links.
    
    ld/testsuite/ChangeLog:
    
    2013-11-26  Will Newton  <will.newton@linaro.org>
    
    	* ld-aarch64/aarch64-elf.exp: Add ifunc-22.
    	* ld-aarch64/ifunc-22.d: New file.
    	* ld-aarch64/ifunc-22.s: Likewise.

diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 3cd3a18..9053635 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -6824,7 +6824,34 @@ elfNN_aarch64_finish_dynamic_symbol (bfd *output_bfd,
 		       + htab->root.sgot->output_offset
 		       + (h->got.offset & ~(bfd_vma) 1));
 
-      if (info->shared && SYMBOL_REFERENCES_LOCAL (info, h))
+      if (h->def_regular
+	  && h->type == STT_GNU_IFUNC)
+	{
+	  if (info->shared)
+	    {
+	      /* Generate R_AARCH64_GLOB_DAT.  */
+	      goto do_glob_dat;
+	    }
+	  else
+	    {
+	      asection *plt;
+
+	      if (!h->pointer_equality_needed)
+		abort ();
+
+	      /* For non-shared object, we can't use .got.plt, which
+		 contains the real function address if we need pointer
+		 equality.  We load the GOT entry with the PLT entry.  */
+	      plt = htab->root.splt ? htab->root.splt : htab->root.iplt;
+	      bfd_put_NN (output_bfd, (plt->output_section->vma
+				       + plt->output_offset
+				       + h->plt.offset),
+			  htab->root.sgot->contents
+			  + (h->got.offset & ~(bfd_vma) 1));
+	      return TRUE;
+	    }
+	}
+      else if (info->shared && SYMBOL_REFERENCES_LOCAL (info, h))
 	{
 	  if (!h->def_regular)
 	    return FALSE;
@@ -6837,6 +6864,7 @@ elfNN_aarch64_finish_dynamic_symbol (bfd *output_bfd,
 	}
       else
 	{
+do_glob_dat:
 	  BFD_ASSERT ((h->got.offset & 1) == 0);
 	  bfd_put_NN (output_bfd, (bfd_vma) 0,
 		      htab->root.sgot->contents + h->got.offset);
diff --git a/ld/testsuite/ld-aarch64/aarch64-elf.exp b/ld/testsuite/ld-aarch64/aarch64-elf.exp
index a6b3ea2..692bf34 100644
--- a/ld/testsuite/ld-aarch64/aarch64-elf.exp
+++ b/ld/testsuite/ld-aarch64/aarch64-elf.exp
@@ -156,3 +156,4 @@ run_dump_test "ifunc-19a"
 run_dump_test "ifunc-19b"
 run_dump_test "ifunc-20"
 run_dump_test "ifunc-21"
+run_dump_test "ifunc-22"
diff --git a/ld/testsuite/ld-aarch64/ifunc-22.d b/ld/testsuite/ld-aarch64/ifunc-22.d
new file mode 100644
index 0000000..f28b039
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-22.d
@@ -0,0 +1,11 @@
+#source: ifunc-22.s
+#objdump: -s -j .got
+#ld: -static
+#target: aarch64*-*-*
+
+# Ensure GOT is populated correctly in static link
+
+.*:     file format elf64-(little|big)aarch64
+
+Contents of section \.got:
+ 4100f0 00000000 00000000 d0004000 00000000  ..........@.....
diff --git a/ld/testsuite/ld-aarch64/ifunc-22.s b/ld/testsuite/ld-aarch64/ifunc-22.s
new file mode 100644
index 0000000..69a87bb
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-22.s
@@ -0,0 +1,14 @@
+	.text
+	.type ifunc, @gnu_indirect_function
+	.global ifunc
+ifunc:
+	ret
+	.size	ifunc, .-ifunc
+	.type _start, @function
+	.globl _start
+_start:
+        adrp    x0, :got:ifunc
+        ldr     x0, [x0, #:got_lo12:ifunc]
+	.size	_start, .-_start
+	.data
+	.xword	ifunc