x86-64: Move PIC check for PC-relative relocations back
authorH.J. Lu <hjl.tools@gmail.com>
Fri, 16 Aug 2019 21:25:15 +0000 (14:25 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Fri, 16 Aug 2019 21:25:58 +0000 (14:25 -0700)
commit 83924b3846361f2f76f9a6e7b5afa01c0eebbd4f
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Tue Feb 5 18:45:23 2019 -0800

    x86-64: Restore PIC check for PCREL reloc against protected symbol

moved PIC check for PC-relative relocations to elf_x86_64_check_relocs.
Since linker defined symbols may not be processed at the time, we need
to move the check back to elf_x86_64_relocate_section.

bfd/

PR ld/24905
* elf64-x86-64.c (elf_x86_64_check_relocs): Move PIC check for
PC-relative relocations back to ...
(elf_x86_64_relocate_section): Here.

ld/

PR ld/24905
* testsuite/ld-x86-64/pr24905-x32.d: New file.
* testsuite/ld-x86-64/pr24905.d: Likewise.
* testsuite/ld-x86-64/pr24905.s: Likewise.
* testsuite/ld-x86-64/pr24905.t: Likewise.
* testsuite/ld-x86-64/x86-64.exp: Run pr24905 and pr24905-x32.

bfd/ChangeLog
bfd/elf64-x86-64.c
ld/ChangeLog
ld/testsuite/ld-x86-64/pr24905-x32.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr24905.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr24905.s [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr24905.t [new file with mode: 0644]
ld/testsuite/ld-x86-64/x86-64.exp

index 868796a8c1077e3d1637f398584056df66051347..962fc1f0375cd4b5633fc48abb19566b5b53be81 100644 (file)
@@ -1,3 +1,10 @@
+2019-08-16  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/24905
+       * elf64-x86-64.c (elf_x86_64_check_relocs): Move PIC check for
+       PC-relative relocations back to ...
+       (elf_x86_64_relocate_section): Here.
+
 2019-08-16  Martin Liska  <mliska@suse.cz>
 
        PR ld/24912
index 34180c7552a36a8a6478eb812f6549c67f414dd5..e5c8003a68e1dc71e84ec10fb434175e26df38ce 100644 (file)
@@ -1864,7 +1864,6 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
       const char *name;
       bfd_boolean size_reloc;
       bfd_boolean converted_reloc;
-      bfd_boolean do_check_pic;
 
       r_symndx = htab->r_sym (rel->r_info);
       r_type = ELF32_R_TYPE (rel->r_info);
@@ -2136,13 +2135,6 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
          size_reloc = TRUE;
          goto do_size;
 
-       case R_X86_64_PC8:
-       case R_X86_64_PC16:
-       case R_X86_64_PC32:
-       case R_X86_64_PC32_BND:
-         do_check_pic = TRUE;
-         goto check_pic;
-
        case R_X86_64_32:
          if (!ABI_64_P (abfd))
            goto pointer;
@@ -2166,11 +2158,13 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
                                        &x86_64_elf_howto_table[r_type]);
          /* Fall through.  */
 
+       case R_X86_64_PC8:
+       case R_X86_64_PC16:
+       case R_X86_64_PC32:
+       case R_X86_64_PC32_BND:
        case R_X86_64_PC64:
        case R_X86_64_64:
 pointer:
-         do_check_pic = FALSE;
-check_pic:
          if (eh != NULL && (sec->flags & SEC_CODE) != 0)
            eh->zero_undefweak |= 0x2;
          /* We are called after all symbols have been resolved.  Only
@@ -2234,69 +2228,6 @@ check_pic:
                }
            }
 
-         if (do_check_pic)
-           {
-             /* Don't complain about -fPIC if the symbol is undefined
-                when building executable unless it is unresolved weak
-                symbol, references a dynamic definition in PIE or
-                -z nocopyreloc is used.  */
-             bfd_boolean no_copyreloc_p
-               = (info->nocopyreloc
-                  || (h != NULL
-                      && !h->root.linker_def
-                      && !h->root.ldscript_def
-                      && eh->def_protected
-                      && elf_has_no_copy_on_protected (h->root.u.def.section->owner)));
-             if ((sec->flags & SEC_ALLOC) != 0
-                 && (sec->flags & SEC_READONLY) != 0
-                 && h != NULL
-                 && ((bfd_link_executable (info)
-                      && ((h->root.type == bfd_link_hash_undefweak
-                           && (eh == NULL
-                               || !UNDEFINED_WEAK_RESOLVED_TO_ZERO (info,
-                                                                    eh)))
-                          || (bfd_link_pie (info)
-                              && !SYMBOL_DEFINED_NON_SHARED_P (h)
-                              && h->def_dynamic)
-                          || (no_copyreloc_p
-                              && h->def_dynamic
-                              && !(h->root.u.def.section->flags & SEC_CODE))))
-                     || bfd_link_dll (info)))
-               {
-                 bfd_boolean fail = FALSE;
-                 if (SYMBOL_REFERENCES_LOCAL_P (info, h))
-                   {
-                     /* Symbol is referenced locally.  Make sure it is
-                        defined locally.  */
-                     fail = !SYMBOL_DEFINED_NON_SHARED_P (h);
-                   }
-                 else if (bfd_link_pie (info))
-                   {
-                     /* We can only use PC-relative relocations in PIE
-                        from non-code sections.  */
-                     if (h->type == STT_FUNC
-                         && (sec->flags & SEC_CODE) != 0)
-                       fail = TRUE;
-                   }
-                 else if (no_copyreloc_p || bfd_link_dll (info))
-                   {
-                     /* Symbol doesn't need copy reloc and isn't
-                        referenced locally.  Don't allow PC-relative
-                        relocations against default and protected
-                        symbols since address of protected function
-                        and location of protected data may not be in
-                        the shared object.   */
-                     fail = (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
-                             || ELF_ST_VISIBILITY (h->other) == STV_PROTECTED);
-                   }
-
-                 if (fail)
-                   return elf_x86_64_need_pic (info, abfd, sec, h,
-                                               symtab_hdr, isym,
-                                               &x86_64_elf_howto_table[r_type]);
-               }
-           }
-
          size_reloc = FALSE;
 do_size:
          if (NEED_DYNAMIC_RELOCATION_P (info, TRUE, h, sec, r_type,
@@ -2497,6 +2428,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
       bfd_boolean relative_reloc;
       bfd_boolean converted_reloc;
       bfd_boolean need_copy_reloc_in_pie;
+      bfd_boolean no_copyreloc_p;
 
       r_type = ELF32_R_TYPE (rel->r_info);
       if (r_type == (int) R_X86_64_GNU_VTINHERIT
@@ -3137,14 +3069,73 @@ use_plt:
        case R_X86_64_PC16:
        case R_X86_64_PC32:
        case R_X86_64_PC32_BND:
+         /* Don't complain about -fPIC if the symbol is undefined when
+            building executable unless it is unresolved weak symbol,
+            references a dynamic definition in PIE or -z nocopyreloc
+            is used.  */
+         no_copyreloc_p
+           = (info->nocopyreloc
+              || (h != NULL
+                  && !h->root.linker_def
+                  && !h->root.ldscript_def
+                  && eh->def_protected
+                  && elf_has_no_copy_on_protected (h->root.u.def.section->owner)));
+
+         if ((input_section->flags & SEC_ALLOC) != 0
+             && (input_section->flags & SEC_READONLY) != 0
+             && h != NULL
+             && ((bfd_link_executable (info)
+                  && ((h->root.type == bfd_link_hash_undefweak
+                       && (eh == NULL
+                           || !UNDEFINED_WEAK_RESOLVED_TO_ZERO (info,
+                                                                eh)))
+                      || (bfd_link_pie (info)
+                          && !SYMBOL_DEFINED_NON_SHARED_P (h)
+                          && h->def_dynamic)
+                      || (no_copyreloc_p
+                          && h->def_dynamic
+                          && !(h->root.u.def.section->flags & SEC_CODE))))
+                 || bfd_link_dll (info)))
+           {
+             bfd_boolean fail = FALSE;
+             if (SYMBOL_REFERENCES_LOCAL_P (info, h))
+               {
+                 /* Symbol is referenced locally.  Make sure it is
+                    defined locally.  */
+                 fail = !SYMBOL_DEFINED_NON_SHARED_P (h);
+               }
+             else if (bfd_link_pie (info))
+               {
+                 /* We can only use PC-relative relocations in PIE
+                    from non-code sections.  */
+                 if (h->type == STT_FUNC
+                     && (sec->flags & SEC_CODE) != 0)
+                   fail = TRUE;
+               }
+             else if (no_copyreloc_p || bfd_link_dll (info))
+               {
+                 /* Symbol doesn't need copy reloc and isn't
+                    referenced locally.  Don't allow PC-relative
+                    relocations against default and protected
+                    symbols since address of protected function
+                    and location of protected data may not be in
+                    the shared object.   */
+                 fail = (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+                         || ELF_ST_VISIBILITY (h->other) == STV_PROTECTED);
+               }
+
+             if (fail)
+               return elf_x86_64_need_pic (info, input_bfd, input_section,
+                                           h, NULL, NULL, howto);
+           }
          /* Since x86-64 has PC-relative PLT, we can use PLT in PIE
             as function address.  */
-         if (h != NULL
-             && (input_section->flags & SEC_CODE) == 0
-             && bfd_link_pie (info)
-             && h->type == STT_FUNC
-             && !h->def_regular
-             && h->def_dynamic)
+         else if (h != NULL
+                  && (input_section->flags & SEC_CODE) == 0
+                  && bfd_link_pie (info)
+                  && h->type == STT_FUNC
+                  && !h->def_regular
+                  && h->def_dynamic)
            goto use_plt;
          /* Fall through.  */
 
index 34d324082358e9e7a726f84e757579bde222d2bb..4837aac2203eef35b3e3d961cd2bf362933a3e2c 100644 (file)
@@ -1,3 +1,12 @@
+2019-08-16  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/24905
+       * testsuite/ld-x86-64/pr24905-x32.d: New file.
+       * testsuite/ld-x86-64/pr24905.d: Likewise.
+       * testsuite/ld-x86-64/pr24905.s: Likewise.
+       * testsuite/ld-x86-64/pr24905.t: Likewise.
+       * testsuite/ld-x86-64/x86-64.exp: Run pr24905 and pr24905-x32.
+
 2019-08-16  Christophe Lyon  <christophe.lyon@linaro.org>
 
        * emulparams/armelf.sh (OTHER_SECTIONS): Add support for noinit
diff --git a/ld/testsuite/ld-x86-64/pr24905-x32.d b/ld/testsuite/ld-x86-64/pr24905-x32.d
new file mode 100644 (file)
index 0000000..e2c6a73
--- /dev/null
@@ -0,0 +1,8 @@
+#source: pr24905.s
+#as: --x32
+#ld: -shared -melf32_x86_64 $srcdir/$subdir/pr24905.t
+#nm: -n
+
+#...
+[0-9a-f]* t EXTERNAL_SYM
+#pass
diff --git a/ld/testsuite/ld-x86-64/pr24905.d b/ld/testsuite/ld-x86-64/pr24905.d
new file mode 100644 (file)
index 0000000..f11834f
--- /dev/null
@@ -0,0 +1,7 @@
+#as: --64
+#ld: -shared -melf_x86_64 $srcdir/$subdir/pr24905.t
+#nm: -n
+
+#...
+[0-9a-f]* t EXTERNAL_SYM
+#pass
diff --git a/ld/testsuite/ld-x86-64/pr24905.s b/ld/testsuite/ld-x86-64/pr24905.s
new file mode 100644 (file)
index 0000000..73a5d58
--- /dev/null
@@ -0,0 +1,6 @@
+       .text
+       .globl  foo
+       .type   foo, @function
+foo:
+       leaq    EXTERNAL_SYM(%rip), %rdi
+       .hidden EXTERNAL_SYM
diff --git a/ld/testsuite/ld-x86-64/pr24905.t b/ld/testsuite/ld-x86-64/pr24905.t
new file mode 100644 (file)
index 0000000..5e7dbd3
--- /dev/null
@@ -0,0 +1 @@
+PROVIDE_HIDDEN(EXTERNAL_SYM = ADDR(.text));
index d815e5d633cc1b8f95336d8f3b89d487a8405ec7..b13cc7df0e9e6097ae5f186d6a46cc2caae40221 100644 (file)
@@ -458,6 +458,8 @@ run_dump_test "pr24458c"
 run_dump_test "pr24458c-x32"
 run_dump_test "pr24721"
 run_dump_test "pr24721-x32"
+run_dump_test "pr24905"
+run_dump_test "pr24905-x32"
 
 if { ![istarget "x86_64-*-linux*"] && ![istarget "x86_64-*-nacl*"]} {
     return