be6651
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
be6651
index 1edf2a0..e27f067 100644 (file)
be6651
--- a/bfd/elfnn-aarch64.c
be6651
+++ b/bfd/elfnn-aarch64.c
be6651
@@ -6869,6 +6889,31 @@ elfNN_aarch64_gc_sweep_hook (bfd *abfd,
be6651
   return TRUE;
be6651
 }
be6651
 
be6651
+/* Return true if we need copy relocation against EH.  */
be6651
+
be6651
+static bfd_boolean
be6651
+need_copy_relocation_p (struct elf_aarch64_link_hash_entry *eh)
be6651
+{
be6651
+  struct elf_dyn_relocs *p;
be6651
+  asection *s;
be6651
+
be6651
+  for (p = eh->dyn_relocs; p != NULL; p = p->next)
be6651
+    {
be6651
+      /* If there is any pc-relative reference, we need to keep copy relocation
be6651
+        to avoid propagating the relocation into runtime that current glibc
be6651
+        does not support.  */
be6651
+      if (p->pc_count)
be6651
+       return TRUE;
be6651
+
be6651
+      s = p->sec->output_section;
be6651
+      /* Need copy relocation if it's against read-only section.  */
be6651
+      if (s != NULL && (s->flags & SEC_READONLY) != 0)
be6651
+       return TRUE;
be6651
+    }
be6651
+
be6651
+  return FALSE;
be6651
+}
be6651
+
be6651
 /* Adjust a symbol defined by a dynamic object and referenced by a
be6651
    regular object.  The current definition is in some section of the
be6651
    dynamic object, but we're not including those sections.  We have to
be6651
@@ -6942,6 +6987,19 @@ elfNN_aarch64_adjust_dynamic_symbol (struct bfd_link_info *info,
be6651
       return TRUE;
be6651
     }
be6651
 
be6651
+  if (ELIMINATE_COPY_RELOCS)
be6651
+    {
be6651
+      struct elf_aarch64_link_hash_entry *eh;
be6651
+      /* If we didn't find any dynamic relocs in read-only sections, then
be6651
+        we'll be keeping the dynamic relocs and avoiding the copy reloc.  */
be6651
+      eh = (struct elf_aarch64_link_hash_entry *) h;
be6651
+      if (!need_copy_relocation_p (eh))
be6651
+       {
be6651
+         h->non_got_ref = 0;
be6651
+         return TRUE;
be6651
+       }
be6651
+    }
be6651
+
be6651
   /* We must allocate the symbol in our .dynbss section, which will
be6651
      become part of the .bss section of the executable.  There will be
be6651
      an entry for this symbol in the .dynsym section.  The dynamic
be6651
diff --git a/ld/testsuite/ld-aarch64/copy-reloc-2.d b/ld/testsuite/ld-aarch64/copy-reloc-2.d
be6651
new file mode 100644 (file)
be6651
index 0000000..87ddccd
be6651
--- /dev/null
be6651
+++ b/ld/testsuite/ld-aarch64/copy-reloc-2.d
be6651
@@ -0,0 +1,7 @@
be6651
+.*
be6651
+DYNAMIC RELOCATION RECORDS
be6651
+OFFSET.*TYPE.*VALUE.*
be6651
+.*R_AARCH64_COPY.*global_[abcd]
be6651
+.*R_AARCH64_COPY.*global_[abcd]
be6651
+.*R_AARCH64_COPY.*global_[abcd]
be6651
+.*R_AARCH64_COPY.*global_[abcd]
be6651
diff --git a/ld/testsuite/ld-aarch64/copy-reloc-eliminate.d b/ld/testsuite/ld-aarch64/copy-reloc-eliminate.d
be6651
new file mode 100644 (file)
be6651
index 0000000..9657d65
be6651
--- /dev/null
be6651
+++ b/ld/testsuite/ld-aarch64/copy-reloc-eliminate.d
be6651
@@ -0,0 +1,4 @@
be6651
+.*
be6651
+DYNAMIC RELOCATION RECORDS
be6651
+OFFSET.*TYPE.*VALUE.*
be6651
+.*R_AARCH64_ABS64.*global_a
be6651
diff --git a/ld/testsuite/ld-aarch64/copy-reloc-exe-2.s b/ld/testsuite/ld-aarch64/copy-reloc-exe-2.s
be6651
new file mode 100644 (file)
be6651
index 0000000..d83658c
be6651
--- /dev/null
be6651
+++ b/ld/testsuite/ld-aarch64/copy-reloc-exe-2.s
be6651
@@ -0,0 +1,32 @@
be6651
+       # expect copy relocation for all these scenarios.
be6651
+       .global p
be6651
+       .global q
be6651
+       .global r
be6651
+       .section        .data.rel.ro,"aw",%progbits
be6651
+       .align  3
be6651
+       .type   p, %object
be6651
+       .size   p, 8
be6651
+p:
be6651
+       .xword  global_a
be6651
+
be6651
+       .type   q, %object
be6651
+       .size   q, 8
be6651
+q:
be6651
+       .xword  global_b
be6651
+
be6651
+       .type   r, %object
be6651
+       .size   r, 8
be6651
+r:
be6651
+       # Any pc-rel relocation as no dynamic linker support on AArch64.
be6651
+       .xword  global_c - .
be6651
+
be6651
+       .text
be6651
+       .global main
be6651
+main:
be6651
+       # Symbols are referenced by any other relocation against read-only
be6651
+       # section.
be6651
+       movz x0, :abs_g0_nc:global_a
be6651
+       adrp x1, global_b
be6651
+       # pc-rel.
be6651
+       adrp x2, global_d
be6651
+       add x2, x2, #:lo12:global_c
be6651
diff --git a/ld/testsuite/ld-aarch64/copy-reloc-exe-eliminate.s b/ld/testsuite/ld-aarch64/copy-reloc-exe-eliminate.s
be6651
new file mode 100644 (file)
be6651
index 0000000..33227aa
be6651
--- /dev/null
be6651
+++ b/ld/testsuite/ld-aarch64/copy-reloc-exe-eliminate.s
be6651
@@ -0,0 +1,7 @@
be6651
+       .global p
be6651
+       .section        .data.rel.ro,"aw",%progbits
be6651
+       .align  3
be6651
+       .type   p, %object
be6651
+       .size   p, 8
be6651
+p:
be6651
+       .xword  global_a
be6651
--- binutils.orig/ld/testsuite/ld-aarch64/copy-reloc-so.s	2017-10-10 16:56:06.347550451 +0100
be6651
+++ binutils-2.27/ld/testsuite/ld-aarch64/copy-reloc-so.s	2017-10-10 16:56:25.926321182 +0100
be6651
@@ -1,6 +1,25 @@
be6651
 	.global global_a
be6651
 	.type	global_a, %object
be6651
 	.size	global_a, 4
be6651
+
be6651
+       .global global_b
be6651
+       .type   global_b, %object
be6651
+       .size   global_b, 4
be6651
+
be6651
+       .global global_c
be6651
+       .type   global_c, %object
be6651
+       .size   global_c, 4
be6651
+
be6651
+       .global global_d
be6651
+       .type   global_d, %object
be6651
+       .size   global_d, 4
be6651
+
be6651
 	.data
be6651
 global_a:
be6651
 	.word 0xcafedead
be6651
+global_b:
be6651
+       .word 0xcafecafe
be6651
+global_c:
be6651
+       .word 0xdeadcafe
be6651
+global_d:
be6651
+       .word 0xdeaddead
be6651
--- binutils.orig/ld/testsuite/ld-aarch64/aarch64-elf.exp	2017-10-10 16:56:06.347550451 +0100
be6651
+++ binutils-2.27/ld/testsuite/ld-aarch64/aarch64-elf.exp	2017-10-10 16:58:19.629989701 +0100
be6651
@@ -292,6 +292,10 @@ set aarch64elflinktests {
be6651
     {} "copy-reloc-so.so"}
be6651
   {"ld-aarch64/exe with copy relocation" "-e0 tmpdir/copy-reloc-so.so" "" ""
be6651
     {copy-reloc-exe.s} {{objdump -R copy-reloc.d}} "copy-reloc"}
be6651
+  {"ld-aarch64/exe with copy relocation 2" "-e0 tmpdir/copy-reloc-so.so" "" ""
be6651
+    {copy-reloc-exe-2.s} {{objdump -R copy-reloc-2.d}} "copy-reloc-2"}
be6651
+  {"ld-aarch64/exe with copy relocation elimination" "-e0 tmpdir/copy-reloc-so.so" "" ""
be6651
+    {copy-reloc-exe-eliminate.s} {{objdump -R copy-reloc-eliminate.d}} "copy-reloc-elimination"}
be6651
 }
be6651
 
be6651
 run_ld_link_tests $aarch64elflinktests
be6651
--- binutils.orig/bfd/elfnn-aarch64.c	2017-10-10 16:56:05.783557056 +0100
be6651
+++ binutils-2.27/bfd/elfnn-aarch64.c	2017-10-10 17:15:02.559298576 +0100
be6651
@@ -246,7 +246,7 @@
be6651
    || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC		\
be6651
    || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_OFF_G1)
be6651
 
be6651
-#define ELIMINATE_COPY_RELOCS 0
be6651
+#define ELIMINATE_COPY_RELOCS 1
be6651
 
be6651
 /* Return size of a relocation entry.  HTAB is the bfd's
be6651
    elf_aarch64_link_hash_entry.  */
be6651
@@ -5154,12 +5154,25 @@ elfNN_aarch64_final_link_relocate (reloc
be6651
       /* When generating a shared object or relocatable executable, these
be6651
          relocations are copied into the output file to be resolved at
be6651
          run time.  */
be6651
-      if (((bfd_link_pic (info) == TRUE)
be6651
-	   || globals->root.is_relocatable_executable)
be6651
-	  && (input_section->flags & SEC_ALLOC)
be6651
-	  && (h == NULL
be6651
-	      || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
be6651
-	      || h->root.type != bfd_link_hash_undefweak))
be6651
+      if ((((bfd_link_pic (info) == TRUE)
be6651
+	    || globals->root.is_relocatable_executable)
be6651
+	   && (input_section->flags & SEC_ALLOC)
be6651
+	   && (h == NULL
be6651
+	       || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
be6651
+	       || h->root.type != bfd_link_hash_undefweak))
be6651
+	  /* Or we are creating an executable, we may need to keep relocations
be6651
+	     for symbols satisfied by a dynamic library if we manage to avoid
be6651
+	     copy relocs for the symbol.  */
be6651
+	  || (ELIMINATE_COPY_RELOCS
be6651
+	      && !bfd_link_pic (info)
be6651
+	      && h != NULL
be6651
+	      && (input_section->flags & SEC_ALLOC)
be6651
+	      && h->dynindx != -1
be6651
+	      && !h->non_got_ref
be6651
+	      && ((h->def_dynamic
be6651
+		   && !h->def_regular)
be6651
+		  || h->root.type == bfd_link_hash_undefweak
be6651
+		  || h->root.type == bfd_link_hash_undefined)))
be6651
 	{
be6651
 	  Elf_Internal_Rela outrel;
be6651
 	  bfd_byte *loc;
be6651
@@ -6777,15 +6790,22 @@ elfNN_aarch64_gc_sweep_hook (bfd *abfd,
be6651
 	    h->plt.refcount -= 1;
be6651
 	  break;
be6651
 
be6651
+	case BFD_RELOC_AARCH64_ADD_LO12:
be6651
 	case BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL:
be6651
 	case BFD_RELOC_AARCH64_ADR_HI21_PCREL:
be6651
 	case BFD_RELOC_AARCH64_ADR_LO21_PCREL:
be6651
+	case BFD_RELOC_AARCH64_LDST128_LO12:
be6651
+	case BFD_RELOC_AARCH64_LDST16_LO12:
be6651
+	case BFD_RELOC_AARCH64_LDST32_LO12:
be6651
+	case BFD_RELOC_AARCH64_LDST64_LO12:
be6651
+	case BFD_RELOC_AARCH64_LDST8_LO12:
be6651
+	case BFD_RELOC_AARCH64_LD_LO19_PCREL:
be6651
 	case BFD_RELOC_AARCH64_MOVW_G0_NC:
be6651
 	case BFD_RELOC_AARCH64_MOVW_G1_NC:
be6651
 	case BFD_RELOC_AARCH64_MOVW_G2_NC:
be6651
 	case BFD_RELOC_AARCH64_MOVW_G3:
be6651
 	case BFD_RELOC_AARCH64_NN:
be6651
-	  if (h != NULL && bfd_link_executable (info))
be6651
+	  if (h != NULL && bfd_link_pic (info))
be6651
 	    {
be6651
 	      if (h->plt.refcount > 0)
be6651
 		h->plt.refcount -= 1;
be6651
@@ -7158,6 +7178,41 @@ elfNN_aarch64_check_relocs (bfd *abfd, s
be6651
 
be6651
       switch (bfd_r_type)
be6651
 	{
be6651
+	case BFD_RELOC_AARCH64_MOVW_G0_NC:
be6651
+	case BFD_RELOC_AARCH64_MOVW_G1_NC:
be6651
+	case BFD_RELOC_AARCH64_MOVW_G2_NC:
be6651
+	case BFD_RELOC_AARCH64_MOVW_G3:
be6651
+	  if (bfd_link_pic (info))
be6651
+	    {
be6651
+	      int howto_index = bfd_r_type - BFD_RELOC_AARCH64_RELOC_START;
be6651
+	      _bfd_error_handler
be6651
+		/* xgettext:c-format */
be6651
+		(_("%B: relocation %s against `%s' can not be used when making "
be6651
+		   "a shared object; recompile with -fPIC"),
be6651
+		 abfd, elfNN_aarch64_howto_table[howto_index].name,
be6651
+		 (h) ? h->root.root.string : "a local symbol");
be6651
+	      bfd_set_error (bfd_error_bad_value);
be6651
+	      return FALSE;
be6651
+	    }
be6651
+	  /* Fall through.  */
be6651
+
be6651
+	case BFD_RELOC_AARCH64_16_PCREL:
be6651
+	case BFD_RELOC_AARCH64_32_PCREL:
be6651
+	case BFD_RELOC_AARCH64_64_PCREL:
be6651
+	case BFD_RELOC_AARCH64_ADD_LO12:
be6651
+	case BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL:
be6651
+	case BFD_RELOC_AARCH64_ADR_HI21_PCREL:
be6651
+	case BFD_RELOC_AARCH64_ADR_LO21_PCREL:
be6651
+	case BFD_RELOC_AARCH64_LDST128_LO12:
be6651
+	case BFD_RELOC_AARCH64_LDST16_LO12:
be6651
+	case BFD_RELOC_AARCH64_LDST32_LO12:
be6651
+	case BFD_RELOC_AARCH64_LDST64_LO12:
be6651
+	case BFD_RELOC_AARCH64_LDST8_LO12:
be6651
+	case BFD_RELOC_AARCH64_LD_LO19_PCREL:
be6651
+	  if (h == NULL || bfd_link_pic (info))
be6651
+	    break;
be6651
+	  /* Fall through.  */
be6651
+
be6651
 	case BFD_RELOC_AARCH64_NN:
be6651
 
be6651
 	  /* We don't need to handle relocs into sections not going into
be6651
@@ -7176,12 +7231,32 @@ elfNN_aarch64_check_relocs (bfd *abfd, s
be6651
 
be6651
 	  /* No need to do anything if we're not creating a shared
be6651
 	     object.  */
be6651
-	  if (! bfd_link_pic (info))
be6651
-	    break;
be6651
+         if (!(bfd_link_pic (info)
be6651
+               /* If on the other hand, we are creating an executable, we
be6651
+                  may need to keep relocations for symbols satisfied by a
be6651
+                  dynamic library if we manage to avoid copy relocs for the
be6651
+                  symbol.
be6651
+
be6651
+                  NOTE: Currently, there is no support of copy relocs
be6651
+                  elimination on pc-relative relocation types, because there is
be6651
+                  no dynamic relocation support for them in glibc.  We still
be6651
+                  record the dynamic symbol reference for them.  This is
be6651
+                  because one symbol may be referenced by both absolute
be6651
+                  relocation (for example, BFD_RELOC_AARCH64_NN) and
be6651
+                  pc-relative relocation.  We need full symbol reference
be6651
+                  information to make correct decision later in
be6651
+                  elfNN_aarch64_adjust_dynamic_symbol.  */
be6651
+               || (ELIMINATE_COPY_RELOCS
be6651
+                   && !bfd_link_pic (info)
be6651
+                   && h != NULL
be6651
+                   && (h->root.type == bfd_link_hash_defweak
be6651
+                       || !h->def_regular))))
be6651
+	   break;
be6651
 
be6651
 	  {
be6651
 	    struct elf_dyn_relocs *p;
be6651
 	    struct elf_dyn_relocs **head;
be6651
+	    int howto_index = bfd_r_type - BFD_RELOC_AARCH64_RELOC_START;
be6651
 
be6651
 	    /* We must copy these reloc types into the output file.
be6651
 	       Create a reloc section in dynobj and make room for
be6651
@@ -7245,6 +7320,8 @@ elfNN_aarch64_check_relocs (bfd *abfd, s
be6651
 
be6651
 	    p->count += 1;
be6651
 
be6651
+	    if (elfNN_aarch64_howto_table[howto_index].pc_relative)
be6651
+	      p->pc_count += 1;
be6651
 	  }
be6651
 	  break;
be6651
 
be6651
@@ -7348,42 +7425,6 @@ elfNN_aarch64_check_relocs (bfd *abfd, s
be6651
 	    break;
be6651
 	  }
be6651
 
be6651
-	case BFD_RELOC_AARCH64_MOVW_G0_NC:
be6651
-	case BFD_RELOC_AARCH64_MOVW_G1_NC:
be6651
-	case BFD_RELOC_AARCH64_MOVW_G2_NC:
be6651
-	case BFD_RELOC_AARCH64_MOVW_G3:
be6651
-	  if (bfd_link_pic (info))
be6651
-	    {
be6651
-	      int howto_index = bfd_r_type - BFD_RELOC_AARCH64_RELOC_START;
be6651
-	      (*_bfd_error_handler)
be6651
-		(_("%B: relocation %s against `%s' can not be used when making "
be6651
-		   "a shared object; recompile with -fPIC"),
be6651
-		 abfd, elfNN_aarch64_howto_table[howto_index].name,
be6651
-		 (h) ? h->root.root.string : "a local symbol");
be6651
-	      bfd_set_error (bfd_error_bad_value);
be6651
-	      return FALSE;
be6651
-	    }
be6651
-
be6651
-	case BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL:
be6651
-	case BFD_RELOC_AARCH64_ADR_HI21_PCREL:
be6651
-	case BFD_RELOC_AARCH64_ADR_LO21_PCREL:
be6651
-	  if (h != NULL && bfd_link_executable (info))
be6651
-	    {
be6651
-	      /* If this reloc is in a read-only section, we might
be6651
-		 need a copy reloc.  We can't check reliably at this
be6651
-		 stage whether the section is read-only, as input
be6651
-		 sections have not yet been mapped to output sections.
be6651
-		 Tentatively set the flag for now, and correct in
be6651
-		 adjust_dynamic_symbol.  */
be6651
-	      h->non_got_ref = 1;
be6651
-	      h->plt.refcount += 1;
be6651
-	      h->pointer_equality_needed = 1;
be6651
-	    }
be6651
-	  /* FIXME:: RR need to handle these in shared libraries
be6651
-	     and essentially bomb out as these being non-PIC
be6651
-	     relocations in shared libraries.  */
be6651
-	  break;
be6651
-
be6651
 	case BFD_RELOC_AARCH64_CALL26:
be6651
 	case BFD_RELOC_AARCH64_JUMP26:
be6651
 	  /* If this is a local symbol then we resolve it