X86-64: Allow copy relocs for building PIE
authorH.J. Lu <hjl.tools@gmail.com>
Tue, 2 Dec 2014 23:14:28 +0000 (15:14 -0800)
committerH.J. Lu <hjl.tools@gmail.com>
Tue, 2 Dec 2014 23:19:25 +0000 (15:19 -0800)
This patch allows copy relocs for non-GOT pc-relative relocation in PIE.

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
bfd/elf64-x86-64.c
ld/testsuite/ChangeLog
ld/testsuite/ld-x86-64/copyreloc-lib.c [new file with mode: 0644]
ld/testsuite/ld-x86-64/copyreloc-main.c [new file with mode: 0644]
ld/testsuite/ld-x86-64/copyreloc-main.out [new file with mode: 0644]
ld/testsuite/ld-x86-64/copyreloc-main1.rd [new file with mode: 0644]
ld/testsuite/ld-x86-64/copyreloc-main2.rd [new file with mode: 0644]
ld/testsuite/ld-x86-64/x86-64.exp

index 010cf55..434db31 100644 (file)
@@ -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
index b10c0c1..60d2d59 100644 (file)
@@ -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)
index de784f7..70201ad 100644 (file)
@@ -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 (file)
index 0000000..cbbc5e2
--- /dev/null
@@ -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 (file)
index 0000000..430eefb
--- /dev/null
@@ -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 (file)
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 (file)
index 0000000..dcb52dc
--- /dev/null
@@ -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 (file)
index 0000000..d78ea2f
--- /dev/null
@@ -0,0 +1,4 @@
+#failif
+#...
+[0-9a-f ]+R_X86_64_NONE.*
+#...
index 886469b..91c9dd9 100644 (file)
@@ -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*"] \