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>
Wed, 3 Dec 2014 13:43:05 +0000 (05:43 -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_adjust_dynamic_symbol): Allocate copy relocs for
PIE.
(elf_x86_64_allocate_dynrelocs): For PIE, discard space for
relocs against symbols which turn out to need copy relocs.
(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 c35c522..681759e 100644 (file)
@@ -1,3 +1,28 @@
+2014-12-02  H.J. Lu  <hongjiu.lu@intel.com>
+
+       * elf64-x86-64.c (elf_x86_64_relocate_section): Check
+       info->executable for symbols which need copy relocs.
+
+2014-12-02  H.J. Lu  <hongjiu.lu@intel.com>
+
+       * elf64-x86-64.c (elf_x86_64_check_relocs): Revert the last
+       change.
+       (elf_x86_64_adjust_dynamic_symbol): Don't check !info->shared
+       with ELIMINATE_COPY_RELOCS.
+       (elf_x86_64_allocate_dynrelocs): For PIE, discard space for
+       relocs against symbols which turn out to need copy relocs.
+
+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-11-30  Alan Modra  <amodra@gmail.com>
 
        PR 16452, 16457
index 3881f60..fb27f0d 100644 (file)
@@ -1053,13 +1053,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)
@@ -2343,7 +2359,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
@@ -2636,20 +2652,28 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
 
       /* Also discard relocs on undefined weak syms with non-default
         visibility.  */
-      if (eh->dyn_relocs != NULL
-         && h->root.type == bfd_link_hash_undefweak)
+      if (eh->dyn_relocs != NULL)
        {
-         if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
+         if (h->root.type == bfd_link_hash_undefweak)
+           {
+             if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
+               eh->dyn_relocs = NULL;
+
+             /* Make sure undefined weak symbols are output as a dynamic
+                symbol in PIEs.  */
+             else if (h->dynindx == -1
+                      && ! h->forced_local
+                      && ! bfd_elf_link_record_dynamic_symbol (info, h))
+               return FALSE;
+           }
+         /* For PIE, discard space for relocs against symbols which
+            turn out to need copy relocs.  */
+         else if (info->executable
+                  && h->needs_copy
+                  && h->def_dynamic
+                  && !h->def_regular)
            eh->dyn_relocs = NULL;
-
-         /* Make sure undefined weak symbols are output as a dynamic
-            symbol in PIEs.  */
-         else if (h->dynindx == -1
-                  && ! h->forced_local
-                  && ! bfd_elf_link_record_dynamic_symbol (info, h))
-           return FALSE;
        }
-
     }
   else if (ELIMINATE_COPY_RELOCS)
     {
@@ -3962,10 +3986,11 @@ elf_x86_64_relocate_section (bfd *output_bfd,
                     defined locally or for a branch.  */
                  fail = !h->def_regular && !branch;
                }
-             else
+             else if (!(info->executable && 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);
                }
@@ -4019,7 +4044,13 @@ 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
+              && !(info->executable
+                   && 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 881f5ce..d00586d 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-01  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/16452
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 54786a7..c8d105b 100644 (file)
@@ -331,4 +331,42 @@ if { [isnative] && [which $CC] != 0 } {
         "-shared -melf32_x86_64 tmpdir/simple-x32.o" "" "--x32"
        {dummy.s} {{readelf {-s --wide} x86-64-x32.rd}} "x86-64-x32"}
     }
+
+    run_cc_link_tests [list \
+       [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 \
+       [list \
+           "Run copyreloc-main with PIE without -fPIE" \
+           "tmpdir/copyreloc-lib.so -pie" \
+           "" \
+           { copyreloc-main.c } \
+           "copyreloc-main" \
+           "copyreloc-main.out" \
+       ] \
+    ]
 }