[PATCH] X86-64: Allow copy relocs for building PIE

H.J. Lu hongjiu.lu@intel.com
Tue Dec 2 23:20:00 GMT 2014


I am checking in this patch to allow copy relocs for non-GOT pc-relative
relocation in PIE.  It makes bfd linker compatible with gold.


H.J.
----
bfd/

	* elf64-x86-64.c (elf_x86_64_create_dynamic_sections): Always
	allow copy relocs for building executables.
	(elf_x86_64_check_relocs): Allow copy relocs for non-GOT
	pc-relative relocation in shared object.
	(elf_x86_64_adjust_dynamic_symbol): Allocate copy relocs for
	PIE.
	(elf_x86_64_relocate_section): Don't copy a pc-relative
	relocation into the output file if the symbol needs copy reloc.

ld/testsuite/

	* ld-x86-64/copyreloc-lib.c: New file.
	* ld-x86-64/copyreloc-main.c: Likewise.
	* ld-x86-64/copyreloc-main.out: Likewise.
	* ld-x86-64/copyreloc-main1.rd: Likewise.
	* ld-x86-64/copyreloc-main2.rd: Likewise.

	* ld-x86-64/x86-64.exp: Run copyreloc tests.
---
 bfd/ChangeLog                             | 11 ++++++++
 bfd/elf64-x86-64.c                        | 46 +++++++++++++++++++++++--------
 ld/testsuite/ChangeLog                    | 10 +++++++
 ld/testsuite/ld-x86-64/copyreloc-lib.c    |  1 +
 ld/testsuite/ld-x86-64/copyreloc-main.c   |  7 +++++
 ld/testsuite/ld-x86-64/copyreloc-main.out |  0
 ld/testsuite/ld-x86-64/copyreloc-main1.rd |  3 ++
 ld/testsuite/ld-x86-64/copyreloc-main2.rd |  4 +++
 ld/testsuite/ld-x86-64/x86-64.exp         | 32 +++++++++++++++++++++
 9 files changed, 103 insertions(+), 11 deletions(-)
 create mode 100644 ld/testsuite/ld-x86-64/copyreloc-lib.c
 create mode 100644 ld/testsuite/ld-x86-64/copyreloc-main.c
 create mode 100644 ld/testsuite/ld-x86-64/copyreloc-main.out
 create mode 100644 ld/testsuite/ld-x86-64/copyreloc-main1.rd
 create mode 100644 ld/testsuite/ld-x86-64/copyreloc-main2.rd

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 010cf55..434db31 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,14 @@
+2014-12-02  H.J. Lu  <hongjiu.lu@intel.com>
+
+	* elf64-x86-64.c (elf_x86_64_create_dynamic_sections): Always
+	allow copy relocs for building executables.
+	(elf_x86_64_check_relocs): Allow copy relocs for non-GOT
+	pc-relative relocation in shared object.
+	(elf_x86_64_adjust_dynamic_symbol): Allocate copy relocs for
+	PIE.
+	(elf_x86_64_relocate_section): Don't copy a pc-relative
+	relocation into the output file if the symbol needs copy reloc.
+
 2014-12-02  Andrew Bennett  <andrew.bennett@imgtec.com>
 
 	* elfxx-mips.c (mips_elf_calculate_relocation): Only check for
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index b10c0c1..60d2d59 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -1060,13 +1060,29 @@ elf_x86_64_create_dynamic_sections (bfd *dynobj,
     return FALSE;
 
   htab->sdynbss = bfd_get_linker_section (dynobj, ".dynbss");
-  if (!info->shared)
-    htab->srelbss = bfd_get_linker_section (dynobj, ".rela.bss");
-
-  if (!htab->sdynbss
-      || (!info->shared && !htab->srelbss))
+  if (!htab->sdynbss)
     abort ();
 
+  if (info->executable)
+    {
+      /* Always allow copy relocs for building executables.  */
+      asection *s;
+      s  = bfd_get_linker_section (dynobj, ".rela.bss");
+      if (s == NULL)
+	{
+	  const struct elf_backend_data *bed = get_elf_backend_data (dynobj);
+	  s = bfd_make_section_anyway_with_flags (dynobj,
+						  ".rela.bss",
+						  (bed->dynamic_sec_flags
+						   | SEC_READONLY));
+	  if (s == NULL
+	      || ! bfd_set_section_alignment (dynobj, s,
+					      bed->s->log_file_align))
+	    return FALSE;
+	}
+      htab->srelbss = s;
+    }
+
   if (!info->no_ld_generated_unwind_info
       && htab->plt_eh_frame == NULL
       && htab->elf.splt != NULL)
@@ -1939,7 +1955,8 @@ do_size:
 	     storing information in the relocs_copied field of the hash
 	     table entry.  A similar situation occurs when creating
 	     shared libraries and symbol visibility changes render the
-	     symbol local.
+	     symbol local.  We allow copy relocs for non-GOT pc-relative
+	     relocation.
 
 	     If on the other hand, we are creating an executable, we
 	     may need to keep relocations for symbols satisfied by a
@@ -1949,6 +1966,7 @@ do_size:
 	       && (sec->flags & SEC_ALLOC) != 0
 	       && (! IS_X86_64_PCREL_TYPE (r_type)
 		   || (h != NULL
+		       && !h->non_got_ref
 		       && (! SYMBOLIC_BIND (info, h)
 			   || h->root.type == bfd_link_hash_defweak
 			   || !h->def_regular))))
@@ -2369,7 +2387,7 @@ elf_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info,
      only references to the symbol are via the global offset table.
      For such cases we need not do anything here; the relocations will
      be handled correctly by relocate_section.	*/
-  if (info->shared)
+  if (!info->executable)
     return TRUE;
 
   /* If there are no references to this symbol that do not use the
@@ -2384,7 +2402,7 @@ elf_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info,
       return TRUE;
     }
 
-  if (ELIMINATE_COPY_RELOCS)
+  if (ELIMINATE_COPY_RELOCS && !info->shared)
     {
       eh = (struct elf_x86_64_link_hash_entry *) h;
       for (p = eh->dyn_relocs; p != NULL; p = p->next)
@@ -4035,10 +4053,11 @@ elf_x86_64_relocate_section (bfd *output_bfd,
 		     defined locally or for a branch.  */
 		  fail = !h->def_regular && !branch;
 		}
-	      else
+	      else if (!h->needs_copy)
 		{
-		  /* Symbol isn't referenced locally.  We only allow
-		     branch to symbol with non-default visibility. */
+		  /* Symbol doesn't need copy reloc and isn't referenced
+		     locally.  We only allow branch to symbol with
+		     non-default visibility. */
 		  fail = (!branch
 			  || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT);
 		}
@@ -4092,7 +4111,12 @@ direct:
 	  if ((input_section->flags & SEC_ALLOC) == 0)
 	    break;
 
+	   /* Don't copy a pc-relative relocation into the output file
+	      if the symbol needs copy reloc.  */
 	  if ((info->shared
+	       && !(h != NULL
+		    && h->needs_copy
+		    && IS_X86_64_PCREL_TYPE (r_type))
 	       && (h == NULL
 		   || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
 		   || h->root.type != bfd_link_hash_undefweak)
diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog
index de784f7..70201ad 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -1,3 +1,13 @@
+2014-12-02  H.J. Lu  <hongjiu.lu@intel.com>
+
+	* ld-x86-64/copyreloc-lib.c: New file.
+	* ld-x86-64/copyreloc-main.c: Likewise.
+	* ld-x86-64/copyreloc-main.out: Likewise.
+	* ld-x86-64/copyreloc-main1.rd: Likewise.
+	* ld-x86-64/copyreloc-main2.rd: Likewise.
+
+	* ld-x86-64/x86-64.exp: Run copyreloc tests.
+
 2014-12-02  Andrew Bennett  <andrew.bennett@imgtec.com>
 
 	* ld-mips-elf/mips-elf.exp: Add undefined weak overflow
diff --git a/ld/testsuite/ld-x86-64/copyreloc-lib.c b/ld/testsuite/ld-x86-64/copyreloc-lib.c
new file mode 100644
index 0000000..cbbc5e2
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/copyreloc-lib.c
@@ -0,0 +1 @@
+int a_glob = 2;
diff --git a/ld/testsuite/ld-x86-64/copyreloc-main.c b/ld/testsuite/ld-x86-64/copyreloc-main.c
new file mode 100644
index 0000000..430eefb
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/copyreloc-main.c
@@ -0,0 +1,7 @@
+extern int a_glob;
+
+int
+main (void)
+{
+  return a_glob != 2;
+}
diff --git a/ld/testsuite/ld-x86-64/copyreloc-main.out b/ld/testsuite/ld-x86-64/copyreloc-main.out
new file mode 100644
index 0000000..e69de29
diff --git a/ld/testsuite/ld-x86-64/copyreloc-main1.rd b/ld/testsuite/ld-x86-64/copyreloc-main1.rd
new file mode 100644
index 0000000..dcb52dc
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/copyreloc-main1.rd
@@ -0,0 +1,3 @@
+#...
+[0-9a-f ]+R_X86_64_COPY+[0-9a-f ]+ +a_glob \+ 0
+#...
diff --git a/ld/testsuite/ld-x86-64/copyreloc-main2.rd b/ld/testsuite/ld-x86-64/copyreloc-main2.rd
new file mode 100644
index 0000000..d78ea2f
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/copyreloc-main2.rd
@@ -0,0 +1,4 @@
+#failif
+#...
+[0-9a-f ]+R_X86_64_NONE.*
+#...
diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp
index 886469b..91c9dd9 100644
--- a/ld/testsuite/ld-x86-64/x86-64.exp
+++ b/ld/testsuite/ld-x86-64/x86-64.exp
@@ -392,6 +392,30 @@ if { [isnative] && [which $CC] != 0 } {
 	    {{readelf {-Wr} plt-main.rd}} \
 	    "plt-main" \
 	] \
+	[list \
+	    "Build copyreloc-lib.so" \
+	    "-shared" \
+	    "-fPIC" \
+	    { copyreloc-lib.c } \
+	    {} \
+	    "copyreloc-lib.so" \
+	] \
+	[list \
+	    "Build copyreloc-main with PIE without -fPIE (1)" \
+	    "tmpdir/copyreloc-lib.so -pie" \
+	    "" \
+	    { copyreloc-main.c } \
+	    {{readelf {-Wr} copyreloc-main1.rd}} \
+	    "copyreloc-main" \
+	] \
+	[list \
+	    "Build copyreloc-main with PIE without -fPIE (2)" \
+	    "tmpdir/copyreloc-lib.so -pie" \
+	    "" \
+	    { copyreloc-main.c } \
+	    {{readelf {-Wr} copyreloc-main2.rd}} \
+	    "copyreloc-main" \
+	] \
     ]
 
     run_ld_link_exec_tests [] [list \
@@ -414,6 +438,14 @@ if { [isnative] && [which $CC] != 0 } {
 	    "plt-main.out" \
 	    "-fPIC" \
 	] \
+	[list \
+	    "Run copyreloc-main with PIE without -fPIE" \
+	    "tmpdir/copyreloc-lib.so -pie" \
+	    "" \
+	    { copyreloc-main.c } \
+	    "copyreloc-main" \
+	    "copyreloc-main.out" \
+	] \
     ]
 
     if { [istarget "x86_64-*-linux*"] \
-- 
1.9.3



More information about the Binutils mailing list