x86-64: Restore PIC check for PCREL reloc against protected symbol
authorH.J. Lu <hjl.tools@gmail.com>
Wed, 6 Feb 2019 02:45:23 +0000 (18:45 -0800)
committerH.J. Lu <hjl.tools@gmail.com>
Wed, 6 Feb 2019 02:45:34 +0000 (18:45 -0800)
commit bd7ab16b4537788ad53521c45469a1bdae84ad4a
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Tue Feb 13 07:34:22 2018 -0800

    x86-64: Generate branch with PLT32 relocation

removed check R_X86_64_PC32 relocation against protected symbols in
shared objects.  Since elf_x86_64_check_relocs is called after we
have seen all input files, we can check for PC-relative relocations in
elf_x86_64_check_relocs.  We should not allow PC-relative relocations
against protected symbols since address of protected function and
location of protected data may not be in the shared object.

bfd/

PR ld/24151
* elf64-x86-64.c (elf_x86_64_need_pic): Check
SYMBOL_DEFINED_NON_SHARED_P instead of def_regular.
(elf_x86_64_relocate_section): Move PIC check for PC-relative
relocations to ...
(elf_x86_64_check_relocs): Here.
(elf_x86_64_finish_dynamic_symbol): Use SYMBOL_DEFINED_NON_SHARED_P
to check if a symbol is defined in a non-shared object.
* elfxx-x86.h (SYMBOL_DEFINED_NON_SHARED_P): New.

ld/

PR ld/24151
* testsuite/ld-x86-64/pr24151a-x32.d: New file.
* testsuite/ld-x86-64/pr24151a.d: Likewise.
* testsuite/ld-x86-64/pr24151a.s: Likewise.
* testsuite/ld-x86-64/x86-64.exp: Run pr24151a and pr24151a-x32.

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

index 5547cd26b9bb10e414b21c690066dad130646e04..22eab1effb616efe892a223a706c621123bd74af 100644 (file)
@@ -1,3 +1,15 @@
+2019-02-05  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/24151
+       * elf64-x86-64.c (elf_x86_64_need_pic): Check
+       SYMBOL_DEFINED_NON_SHARED_P instead of def_regular.
+       (elf_x86_64_relocate_section): Move PIC check for PC-relative
+       relocations to ...
+       (elf_x86_64_check_relocs): Here.
+       (elf_x86_64_finish_dynamic_symbol): Use SYMBOL_DEFINED_NON_SHARED_P
+       to check if a symbol is defined in a non-shared object.
+       * elfxx-x86.h (SYMBOL_DEFINED_NON_SHARED_P): New.
+
 2019-01-21  Sergio Durigan Junior  <sergiodj@redhat.com>
 
        * elf32-arm.c (elf32_arm_final_link_relocate): Use 'llabs' instead
index c7d8bca710215008a452908c8bb7903500cdb893..6a4b366fddacae313e73e77e5eed0596d51d2a98 100644 (file)
@@ -1426,7 +1426,7 @@ elf_x86_64_need_pic (struct bfd_link_info *info,
          break;
        }
 
-      if (!h->def_regular && !h->def_dynamic)
+      if (!SYMBOL_DEFINED_NON_SHARED_P (h) && !h->def_dynamic)
        und = _("undefined ");
     }
   else
@@ -1855,6 +1855,7 @@ 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);
@@ -2130,6 +2131,13 @@ 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;
@@ -2153,13 +2161,11 @@ 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
@@ -2223,6 +2229,67 @@ pointer:
                }
            }
 
+         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
+                      && 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,
@@ -3065,56 +3132,14 @@ 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.  */
-         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
-                       && !resolved_to_zero)
-                      || (bfd_link_pie (info)
-                          && !h->def_regular
-                          && h->def_dynamic)
-                      || ((info->nocopyreloc
-                           || (eh->def_protected
-                               && elf_has_no_copy_on_protected (h->root.u.def.section->owner)))
-                          && 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 = !(h->def_regular || ELF_COMMON_DEF_P (h));
-               }
-             else if (!(bfd_link_pie (info)
-                        && (h->needs_copy || eh->needs_copy)))
-               {
-                 /* Symbol doesn't need copy reloc and isn't referenced
-                    locally.  Address of protected function may not be
-                    reachable at run-time.  */
-                 fail = (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
-                         || (ELF_ST_VISIBILITY (h->other) == STV_PROTECTED
-                             && h->type == STT_FUNC));
-               }
-
-             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.  */
-         else if (h != NULL
-                  && (input_section->flags & SEC_CODE) == 0
-                  && bfd_link_pie (info)
-                  && h->type == STT_FUNC
-                  && !h->def_regular
-                  && h->def_dynamic)
+         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.  */
 
@@ -4271,7 +4296,7 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
       else if (bfd_link_pic (info)
               && SYMBOL_REFERENCES_LOCAL_P (info, h))
        {
-         if (!(h->def_regular || ELF_COMMON_DEF_P (h)))
+         if (!SYMBOL_DEFINED_NON_SHARED_P (h))
            return FALSE;
          BFD_ASSERT((h->got.offset & 1) != 0);
          rela.r_info = htab->r_info (0, R_X86_64_RELATIVE);
index dce24dc10690366c3d14d83c7cb82846db1ae928..28d540b83b3fb9dbb6a6980b5c67cdd7998b4e00 100644 (file)
        || (ELF_ST_VISIBILITY ((H)->other) \
           && (H)->root.type == bfd_link_hash_undefweak))
 
+/* TRUE if this symbol isn't defined by a shared object.  */
+#define SYMBOL_DEFINED_NON_SHARED_P(H) \
+  ((H)->def_regular \
+   || (H)->root.linker_def \
+   || (H)->root.ldscript_def \
+   || ELF_COMMON_DEF_P (H))
+
 /* TRUE if relative relocation should be generated.  GOT reference to
    global symbol in PIC will lead to dynamic symbol.  It becomes a
    problem when "time" or "times" is defined as a variable in an
index 5713b0020c64f50a1d130c33ef9ca5828bca24b5..262f7bf535882b116f0dc47cd92ea239c73924db 100644 (file)
@@ -1,3 +1,11 @@
+2019-02-05  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/24151
+       * testsuite/ld-x86-64/pr24151a-x32.d: New file.
+       * testsuite/ld-x86-64/pr24151a.d: Likewise.
+       * testsuite/ld-x86-64/pr24151a.s: Likewise.
+       * testsuite/ld-x86-64/x86-64.exp: Run pr24151a and pr24151a-x32.
+
 2019-01-31  Alan Modra  <amodra@gmail.com>
 
        * NEWS: Mention -t change.
diff --git a/ld/testsuite/ld-x86-64/pr24151a-x32.d b/ld/testsuite/ld-x86-64/pr24151a-x32.d
new file mode 100644 (file)
index 0000000..130611d
--- /dev/null
@@ -0,0 +1,4 @@
+#source: pr24151a.s
+#as: --x32
+#ld: -shared -melf32_x86_64
+#error: .*relocation R_X86_64_PC32 against protected symbol `foo' can not be used when making a shared object
diff --git a/ld/testsuite/ld-x86-64/pr24151a.d b/ld/testsuite/ld-x86-64/pr24151a.d
new file mode 100644 (file)
index 0000000..783b85a
--- /dev/null
@@ -0,0 +1,3 @@
+#as: --64
+#ld: -shared -melf_x86_64
+#error: .*relocation R_X86_64_PC32 against protected symbol `foo' can not be used when making a shared object
diff --git a/ld/testsuite/ld-x86-64/pr24151a.s b/ld/testsuite/ld-x86-64/pr24151a.s
new file mode 100644 (file)
index 0000000..e4ec7c8
--- /dev/null
@@ -0,0 +1,9 @@
+       .text
+       .globl  bar
+       .type   bar,@function
+bar:
+       movl    $30, foo(%rip)
+       .size   bar, .-bar
+       .protected foo
+       .type   foo,@object
+       .comm   foo,4,4
index 86b163fc7a2de799d9795ed44c31e11a748e80ec..5eb556515faf395cc7b4369d274a73b9f458ccd8 100644 (file)
@@ -424,6 +424,8 @@ run_dump_test "pr23486d-x32"
 run_dump_test "pr23854"
 run_dump_test "pr23930"
 run_dump_test "pr23930-x32"
+run_dump_test "pr24151a"
+run_dump_test "pr24151a-x32"
 
 if { ![istarget "x86_64-*-linux*"] && ![istarget "x86_64-*-nacl*"]} {
     return