Disallow copy relocation against protected data symbol
authorH.J. Lu <hjl.tools@gmail.com>
Sun, 27 Aug 2017 02:22:26 +0000 (19:22 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Sun, 27 Aug 2017 02:26:21 +0000 (19:26 -0700)
We shpouldn't generate copy relocation to resolve reference to protected
data symbol defined in shared object with the NO_COPY_ON_PROTECTED
property.  This patch adds a bit to elf_obj_tdata as well as
elf_i386_link_hash_entry and elf_x86_64_link_hash_entry to track the bfd
with the NO_COPY_ON_PROTECTED property as well as protected symbol
defined in shared object.  extern_protected_data is set to FALSE if any
input relocatable file contains the NO_COPY_ON_PROTECTED property.

bfd/

PR ld/21997
* elf-bfd.h (elf_obj_tdata): Use ENUM_BITFIELD on object_id,
dyn_lib_class and has_gnu_symbols.  Change bad_symtab to bitfield.
Add a has_no_copy_on_protected bitfield.
(elf_has_no_copy_on_protected): New.
* elf-properties.c (_bfd_elf_parse_gnu_properties): Set
elf_has_no_copy_on_protected for GNU_PROPERTY_NO_COPY_ON_PROTECTED.
(elf_merge_gnu_property_list): Likewise.
(_bfd_elf_link_setup_gnu_properties): Set extern_protected_data
to FALSE for elf_has_no_copy_on_protected.
* elf32-i386.c (SYMBOL_NO_COPYRELOC): New.
(elf_i386_link_hash_entry): Add def_protected.
(elf_i386_adjust_dynamic_symbol): Also check SYMBOL_NO_COPYRELOC
when checking info->nocopyreloc.
(elf_i386_link_setup_gnu_properties): Don't set
extern_protected_data here.
(elf_i386_merge_symbol_attribute): New function.
(elf_backend_merge_symbol_attribute): New.
* elf64-x86-64.c (SYMBOL_NO_COPYRELOC): New.
(elf_x86_64_link_hash_entry): Add def_protected.
(elf_x86_64_need_pic): Report protected symbol for def_protected.
(elf_x86_64_adjust_dynamic_symbol): Also check SYMBOL_NO_COPYRELOC
when checking info->nocopyreloc.
(elf_x86_64_relocate_section): Also check for R_X86_64_PC32
relocation run-time overflow and unresolvable R_X86_64_32S
relocation against protected data symbol defined in shared object
with GNU_PROPERTY_NO_COPY_ON_PROTECTED.
(elf_x86_64_link_setup_gnu_properties): Don't set
extern_protected_data here.
(elf_x86_64_merge_symbol_attribute): New function.
(elf_backend_merge_symbol_attribute): New.

ld/

PR ld/21997
* testsuite/ld-i386/i386.exp: Run PR ld/21997 tests.
* testsuite/ld-x86-64/x86-64.exp: Likewise.
* testsuite/ld-i386/pr21997-1a.S: New file.
* testsuite/ld-i386/pr21997-1b.c: Likewise.
* testsuite/ld-i386/pr21997-1c.S: Likewise.
* testsuite/ld-x86-64/pr21997-1a.S: Likewise.
* testsuite/ld-x86-64/pr21997-1a.err: Likewise.
* testsuite/ld-x86-64/pr21997-1b.c: Likewise.
* testsuite/ld-x86-64/pr21997-1b.err: Likewise.
* testsuite/ld-x86-64/pr21997-1c.c: Likewise.

16 files changed:
bfd/ChangeLog
bfd/elf-bfd.h
bfd/elf-properties.c
bfd/elf32-i386.c
bfd/elf64-x86-64.c
ld/ChangeLog
ld/testsuite/ld-i386/i386.exp
ld/testsuite/ld-i386/pr21997-1a.S [new file with mode: 0644]
ld/testsuite/ld-i386/pr21997-1b.c [new file with mode: 0644]
ld/testsuite/ld-i386/pr21997-1c.S [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr21997-1a.S [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr21997-1a.err [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr21997-1b.c [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr21997-1b.err [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr21997-1c.c [new file with mode: 0644]
ld/testsuite/ld-x86-64/x86-64.exp

index e785d0e901224a6e0780ceb973ceecb6227179da..8f84db80302c1484224d9011fa5c551b9c57d78f 100644 (file)
@@ -1,3 +1,37 @@
+2017-08-26  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/21997
+       * elf-bfd.h (elf_obj_tdata): Use ENUM_BITFIELD on object_id,
+       dyn_lib_class and has_gnu_symbols.  Change bad_symtab to bitfield.
+       Add a has_no_copy_on_protected bitfield.
+       (elf_has_no_copy_on_protected): New.
+       * elf-properties.c (_bfd_elf_parse_gnu_properties): Set
+       elf_has_no_copy_on_protected for GNU_PROPERTY_NO_COPY_ON_PROTECTED.
+       (elf_merge_gnu_property_list): Likewise.
+       (_bfd_elf_link_setup_gnu_properties): Set extern_protected_data
+       to FALSE for elf_has_no_copy_on_protected.
+       * elf32-i386.c (SYMBOL_NO_COPYRELOC): New.
+       (elf_i386_link_hash_entry): Add def_protected.
+       (elf_i386_adjust_dynamic_symbol): Also check SYMBOL_NO_COPYRELOC
+       when checking info->nocopyreloc.
+       (elf_i386_link_setup_gnu_properties): Don't set
+       extern_protected_data here.
+       (elf_i386_merge_symbol_attribute): New function.
+       (elf_backend_merge_symbol_attribute): New.
+       * elf64-x86-64.c (SYMBOL_NO_COPYRELOC): New.
+       (elf_x86_64_link_hash_entry): Add def_protected.
+       (elf_x86_64_need_pic): Report protected symbol for def_protected.
+       (elf_x86_64_adjust_dynamic_symbol): Also check SYMBOL_NO_COPYRELOC
+       when checking info->nocopyreloc.
+       (elf_x86_64_relocate_section): Also check for R_X86_64_PC32
+       relocation run-time overflow and unresolvable R_X86_64_32S
+       relocation against protected data symbol defined in shared object
+       with GNU_PROPERTY_NO_COPY_ON_PROTECTED.
+       (elf_x86_64_link_setup_gnu_properties): Don't set
+       extern_protected_data here.
+       (elf_x86_64_merge_symbol_attribute): New function.
+       (elf_backend_merge_symbol_attribute): New.
+
 2017-08-26  Alan Modra  <amodra@gmail.com>
 
        * elf32-ppc.c (must_be_dyn_reloc): Use bfd_link_dll.  Comment.
index 83958e41e074d62b646e0011a511717223e0f505..79b9dbc1807b79e1f4fccfa8b77be78b1bdbdc0d 100644 (file)
@@ -1887,21 +1887,27 @@ struct elf_obj_tdata
 
   /* An identifier used to distinguish different target
      specific extensions to this structure.  */
-  enum elf_target_id object_id;
+  ENUM_BITFIELD (elf_target_id) object_id : 6;
 
   /* Whether a dyanmic object was specified normally on the linker
      command line, or was specified when --as-needed was in effect,
      or was found via a DT_NEEDED entry.  */
-  enum dynamic_lib_link_class dyn_lib_class;
+  ENUM_BITFIELD (dynamic_lib_link_class) dyn_lib_class : 4;
+
+  /* Whether if the bfd contains symbols that have the STT_GNU_IFUNC
+     symbol type or STB_GNU_UNIQUE binding.  */
+  ENUM_BITFIELD (elf_gnu_symbols) has_gnu_symbols : 3;
+
+  /* Whether if the bfd contains the GNU_PROPERTY_NO_COPY_ON_PROTECTED
+     property.  */
+  unsigned int has_no_copy_on_protected : 1;
 
   /* Irix 5 often screws up the symbol table, sorting local symbols
      after global symbols.  This flag is set if the symbol table in
      this BFD appears to be screwed up.  If it is, we ignore the
      sh_info field in the symbol table header, and always read all the
      symbols.  */
-  bfd_boolean bad_symtab;
-
-  enum elf_gnu_symbols has_gnu_symbols;
+  unsigned int bad_symtab : 1;
 
   /* Information grabbed from an elf core file.  */
   struct core_elf_obj_tdata *core;
@@ -1956,6 +1962,8 @@ struct elf_obj_tdata
 #define elf_other_obj_attributes_proc(bfd) \
   (elf_other_obj_attributes (bfd) [OBJ_ATTR_PROC])
 #define elf_properties(bfd) (elf_tdata (bfd) -> properties)
+#define elf_has_no_copy_on_protected(bfd) \
+  (elf_tdata(bfd) -> has_no_copy_on_protected)
 \f
 extern void _bfd_elf_swap_verdef_in
   (bfd *, const Elf_External_Verdef *, Elf_Internal_Verdef *);
index 13d620d9c47478e7906eecda22422b4d8568571d..f367aa69417ce62df2ba897cd40a5d7128568a82 100644 (file)
@@ -168,6 +168,7 @@ bad_size:
                  return FALSE;
                }
              prop = _bfd_elf_get_property (abfd, type, datasz);
+             elf_has_no_copy_on_protected (abfd) = TRUE;
              prop->pr_kind = property_number;
              goto next;
 
@@ -290,6 +291,9 @@ elf_merge_gnu_property_list (struct bfd_link_info *info, bfd *abfd,
   for (p = *listp; p != NULL; p = p->next)
     if (elf_merge_gnu_properties (info, abfd, NULL, &p->property))
       {
+       if (p->property.pr_type == GNU_PROPERTY_NO_COPY_ON_PROTECTED)
+         elf_has_no_copy_on_protected (abfd) = TRUE;
+
        pr = _bfd_elf_get_property (abfd, p->property.pr_type,
                                    p->property.pr_datasz);
        /* It must be a new property.  */
@@ -489,6 +493,11 @@ _bfd_elf_link_setup_gnu_properties (struct bfd_link_info *info)
 
       /* Cache the section contents for elf_link_input_bfd.  */
       elf_section_data (sec)->this_hdr.contents = contents;
+
+      /* If GNU_PROPERTY_NO_COPY_ON_PROTECTED is set, protected data
+        symbol is defined in the shared object.  */
+      if (elf_has_no_copy_on_protected (first_pbfd))
+       info->extern_protected_data = FALSE;
     }
 
   return first_pbfd;
index 179dc434dc36dc362f7e0eef85417e1a5afbe387..69b41a54f91614c6c34e4c7424d41649157f30d6 100644 (file)
@@ -956,6 +956,18 @@ static const struct elf_i386_backend_data elf_i386_arch_bed =
               || (EH)->has_non_got_reloc                       \
               || !(INFO)->dynamic_undefined_weak))))
 
+/* Should copy relocation be generated for a symbol.  Don't generate
+   copy relocation against a protected symbol defined in a shared
+   object with GNU_PROPERTY_NO_COPY_ON_PROTECTED.  */
+#define SYMBOL_NO_COPYRELOC(INFO, EH) \
+  ((EH)->def_protected \
+   && ((EH)->elf.root.type == bfd_link_hash_defined \
+       || (EH)->elf.root.type == bfd_link_hash_defweak) \
+   && elf_has_no_copy_on_protected ((EH)->elf.root.u.def.section->owner) \
+   && ((EH)->elf.root.u.def.section->owner->flags & DYNAMIC) != 0 \
+   && ((EH)->elf.root.u.def.section->flags & SEC_CODE) == 0)
+
+
 /* i386 ELF linker hash entry.  */
 
 struct elf_i386_link_hash_entry
@@ -998,6 +1010,9 @@ struct elf_i386_link_hash_entry
   /* TRUE if symbol is __tls_get_addr.  */
   unsigned int tls_get_addr : 1;
 
+  /* TRUE if symbol is defined as a protected symbol.  */
+  unsigned int def_protected : 1;
+
   /* Reference count of C/C++ function pointer relocations in read-write
      section which can be resolved at run-time.  */
   bfd_signed_vma func_pointer_refcount;
@@ -2590,6 +2605,8 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info,
        the link may change h->type.  So fix it now.  */
     h->plt.offset = (bfd_vma) -1;
 
+  eh = (struct elf_i386_link_hash_entry *) h;
+
   /* If this is a weak symbol, and there is a real definition, the
      processor independent code will have arranged for us to see the
      real definition first, and we can just use the same value.  */
@@ -2599,7 +2616,9 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info,
                  || h->u.weakdef->root.type == bfd_link_hash_defweak);
       h->root.u.def.section = h->u.weakdef->root.u.def.section;
       h->root.u.def.value = h->u.weakdef->root.u.def.value;
-      if (ELIMINATE_COPY_RELOCS || info->nocopyreloc)
+      if (ELIMINATE_COPY_RELOCS
+         || info->nocopyreloc
+         || SYMBOL_NO_COPYRELOC (info, eh))
        h->non_got_ref = h->u.weakdef->non_got_ref;
       return TRUE;
     }
@@ -2617,12 +2636,11 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info,
   /* If there are no references to this symbol that do not use the
      GOT nor R_386_GOTOFF relocation, we don't need to generate a copy
      reloc.  */
-  eh = (struct elf_i386_link_hash_entry *) h;
   if (!h->non_got_ref && !eh->gotoff_ref)
     return TRUE;
 
   /* If -z nocopyreloc was given, we won't generate them either.  */
-  if (info->nocopyreloc)
+  if (info->nocopyreloc || SYMBOL_NO_COPYRELOC (info, eh))
     {
       h->non_got_ref = 0;
       return TRUE;
@@ -6802,68 +6820,39 @@ elf_i386_link_setup_gnu_properties (struct bfd_link_info *info)
          break;
       }
 
-  if (ebfd != NULL)
+  if (ebfd != NULL && features)
     {
-      if (features)
+      /* If features is set, add GNU_PROPERTY_X86_FEATURE_1_IBT and
+        GNU_PROPERTY_X86_FEATURE_1_SHSTK.  */
+      prop = _bfd_elf_get_property (ebfd,
+                                   GNU_PROPERTY_X86_FEATURE_1_AND,
+                                   4);
+      prop->u.number |= features;
+      prop->pr_kind = property_number;
+
+      /* Create the GNU property note section if needed.  */
+      if (pbfd == NULL)
        {
-         /* If features is set, add GNU_PROPERTY_X86_FEATURE_1_IBT and
-            GNU_PROPERTY_X86_FEATURE_1_SHSTK.  */
-         prop = _bfd_elf_get_property (ebfd,
-                                       GNU_PROPERTY_X86_FEATURE_1_AND,
-                                       4);
-         prop->u.number |= features;
-         prop->pr_kind = property_number;
-
-         /* Create the GNU property note section if needed.  */
-         if (pbfd == NULL)
-           {
-             sec = bfd_make_section_with_flags (ebfd,
-                                                NOTE_GNU_PROPERTY_SECTION_NAME,
-                                                (SEC_ALLOC
-                                                 | SEC_LOAD
-                                                 | SEC_IN_MEMORY
-                                                 | SEC_READONLY
-                                                 | SEC_HAS_CONTENTS
-                                                 | SEC_DATA));
-             if (sec == NULL)
-               info->callbacks->einfo (_("%F: failed to create GNU property section\n"));
+         sec = bfd_make_section_with_flags (ebfd,
+                                            NOTE_GNU_PROPERTY_SECTION_NAME,
+                                            (SEC_ALLOC
+                                             | SEC_LOAD
+                                             | SEC_IN_MEMORY
+                                             | SEC_READONLY
+                                             | SEC_HAS_CONTENTS
+                                             | SEC_DATA));
+         if (sec == NULL)
+           info->callbacks->einfo (_("%F: failed to create GNU property section\n"));
 
-             if (!bfd_set_section_alignment (ebfd, sec, 2))
-               {
+         if (!bfd_set_section_alignment (ebfd, sec, 2))
+           {
 error_alignment:
-                 info->callbacks->einfo (_("%F%A: failed to align section\n"),
-                                         sec);
-               }
-
-             elf_section_type (sec) = SHT_NOTE;
+             info->callbacks->einfo (_("%F%A: failed to align section\n"),
+                                     sec);
            }
-       }
 
-      /* Check GNU_PROPERTY_NO_COPY_ON_PROTECTED.  */
-      for (; pbfd != NULL; pbfd = pbfd->link.next)
-       if (bfd_get_flavour (pbfd) == bfd_target_elf_flavour
-           && (pbfd->flags
-               & (DYNAMIC | BFD_LINKER_CREATED | BFD_PLUGIN)) == 0)
-         {
-           elf_property_list *p;
-
-           /* The property list is sorted in order of type.  */
-           for (p = elf_properties (pbfd); p != NULL; p = p->next)
-             {
-               if (GNU_PROPERTY_NO_COPY_ON_PROTECTED
-                   == p->property.pr_type)
-                 {
-                   /* Clear extern_protected_data if
-                      GNU_PROPERTY_NO_COPY_ON_PROTECTED is
-                      set on any input relocatable file.  */
-                   info->extern_protected_data = FALSE;
-                   break;
-                 }
-               else if (GNU_PROPERTY_NO_COPY_ON_PROTECTED
-                        < p->property.pr_type)
-                 break;
-             }
-         }
+         elf_section_type (sec) = SHT_NOTE;
+       }
     }
 
   pbfd = _bfd_elf_link_setup_gnu_properties (info);
@@ -7163,6 +7152,21 @@ elf_i386_link_check_relocs (bfd *abfd, struct bfd_link_info *info)
   return _bfd_elf_link_check_relocs (abfd, info);
 }
 
+static void
+elf_i386_merge_symbol_attribute (struct elf_link_hash_entry *h,
+                                const Elf_Internal_Sym *isym,
+                                bfd_boolean definition,
+                                bfd_boolean dynamic ATTRIBUTE_UNUSED)
+{
+  if (definition)
+    {
+      struct elf_i386_link_hash_entry *eh
+       = (struct elf_i386_link_hash_entry *) h;
+      eh->def_protected = (ELF_ST_VISIBILITY (isym->st_other)
+                          == STV_PROTECTED);
+    }
+}
+
 #define TARGET_LITTLE_SYM              i386_elf32_vec
 #define TARGET_LITTLE_NAME             "elf32-i386"
 #define ELF_ARCH                       bfd_arch_i386
@@ -7218,6 +7222,7 @@ elf_i386_link_check_relocs (bfd *abfd, struct bfd_link_info *info)
 #define elf_backend_parse_gnu_properties      elf_i386_parse_gnu_properties
 #define elf_backend_merge_gnu_properties      elf_i386_merge_gnu_properties
 #define elf_backend_setup_gnu_properties      elf_i386_link_setup_gnu_properties
+#define elf_backend_merge_symbol_attribute    elf_i386_merge_symbol_attribute
 
 #include "elf32-target.h"
 
index 1b8d9ee388d0dc6f569de096679f11b4f9c5dd16..6e4c067732e7f3485c331eec40a08d59d79e7f0a 100644 (file)
@@ -1061,6 +1061,17 @@ static const struct elf_x86_64_backend_data elf_x86_64_arch_bed =
               || (EH)->has_non_got_reloc                       \
               || !(INFO)->dynamic_undefined_weak))))
 
+/* Should copy relocation be generated for a symbol.  Don't generate
+   copy relocation against a protected symbol defined in a shared
+   object with GNU_PROPERTY_NO_COPY_ON_PROTECTED.  */
+#define SYMBOL_NO_COPYRELOC(INFO, EH) \
+  ((EH)->def_protected \
+   && ((EH)->elf.root.type == bfd_link_hash_defined \
+       || (EH)->elf.root.type == bfd_link_hash_defweak) \
+   && elf_has_no_copy_on_protected ((EH)->elf.root.u.def.section->owner) \
+   && ((EH)->elf.root.u.def.section->owner->flags & DYNAMIC) != 0 \
+   && ((EH)->elf.root.u.def.section->flags & SEC_CODE) == 0)
+
 /* x86-64 ELF linker hash entry.  */
 
 struct elf_x86_64_link_hash_entry
@@ -1104,6 +1115,9 @@ struct elf_x86_64_link_hash_entry
   /* TRUE if symbol is __tls_get_addr.  */
   unsigned int tls_get_addr : 1;
 
+  /* TRUE if symbol is defined as a protected symbol.  */
+  unsigned int def_protected : 1;
+
   /* Reference count of C/C++ function pointer relocations in read-write
      section which can be resolved at run-time.  */
   bfd_signed_vma func_pointer_refcount;
@@ -1908,7 +1922,10 @@ elf_x86_64_need_pic (struct bfd_link_info *info,
          v = _("protected symbol ");
          break;
        default:
-         v = _("symbol ");
+         if (((struct elf_x86_64_link_hash_entry *) h)->def_protected)
+           v = _("protected symbol ");
+         else
+           v = _("symbol ");
          pic = _("; recompile with -fPIC");
          break;
        }
@@ -3043,6 +3060,8 @@ elf_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info,
        the link may change h->type.  So fix it now.  */
     h->plt.offset = (bfd_vma) -1;
 
+  eh = (struct elf_x86_64_link_hash_entry *) h;
+
   /* If this is a weak symbol, and there is a real definition, the
      processor independent code will have arranged for us to see the
      real definition first, and we can just use the same value.         */
@@ -3052,9 +3071,10 @@ elf_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info,
                  || h->u.weakdef->root.type == bfd_link_hash_defweak);
       h->root.u.def.section = h->u.weakdef->root.u.def.section;
       h->root.u.def.value = h->u.weakdef->root.u.def.value;
-      if (ELIMINATE_COPY_RELOCS || info->nocopyreloc)
+      if (ELIMINATE_COPY_RELOCS
+         || info->nocopyreloc
+         || SYMBOL_NO_COPYRELOC (info, eh))
        {
-         eh = (struct elf_x86_64_link_hash_entry *) h;
          h->non_got_ref = h->u.weakdef->non_got_ref;
          eh->needs_copy = h->u.weakdef->needs_copy;
        }
@@ -3077,7 +3097,7 @@ elf_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info,
     return TRUE;
 
   /* If -z nocopyreloc was given, we won't generate them either.  */
-  if (info->nocopyreloc)
+  if (info->nocopyreloc || SYMBOL_NO_COPYRELOC (info, eh))
     {
       h->non_got_ref = 0;
       return TRUE;
@@ -4950,7 +4970,9 @@ do_ifunc_pointer:
              && ((bfd_link_executable (info)
                   && ((h->root.type == bfd_link_hash_undefweak
                        && !resolved_to_zero)
-                      || (info->nocopyreloc
+                      || ((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)))
@@ -5724,7 +5746,10 @@ direct:
          switch (r_type)
            {
            case R_X86_64_32S:
-             if (info->nocopyreloc
+             sec = h->root.u.def.section;
+             if ((info->nocopyreloc
+                  || (eh->def_protected
+                      && elf_has_no_copy_on_protected (h->root.u.def.section->owner)))
                  && !(h->root.u.def.section->flags & SEC_CODE))
                return elf_x86_64_need_pic (info, input_bfd, input_section,
                                            h, NULL, NULL, howto);
@@ -7137,6 +7162,21 @@ elf_x86_64_merge_symbol (struct elf_link_hash_entry *h,
   return TRUE;
 }
 
+static void
+elf_x86_64_merge_symbol_attribute (struct elf_link_hash_entry *h,
+                                  const Elf_Internal_Sym *isym,
+                                  bfd_boolean definition,
+                                  bfd_boolean dynamic ATTRIBUTE_UNUSED)
+{
+  if (definition)
+    {
+      struct elf_x86_64_link_hash_entry *eh
+       = (struct elf_x86_64_link_hash_entry *) h;
+      eh->def_protected = (ELF_ST_VISIBILITY (isym->st_other)
+                          == STV_PROTECTED);
+    }
+}
+
 static int
 elf_x86_64_additional_program_headers (bfd *abfd,
                                       struct bfd_link_info *info ATTRIBUTE_UNUSED)
@@ -7349,69 +7389,40 @@ elf_x86_64_link_setup_gnu_properties (struct bfd_link_info *info)
          break;
       }
 
-  if (ebfd != NULL)
+  if (ebfd != NULL && features)
     {
-      if (features)
+      /* If features is set, add GNU_PROPERTY_X86_FEATURE_1_IBT and
+        GNU_PROPERTY_X86_FEATURE_1_SHSTK.  */
+      prop = _bfd_elf_get_property (ebfd,
+                                   GNU_PROPERTY_X86_FEATURE_1_AND,
+                                   4);
+      prop->u.number |= features;
+      prop->pr_kind = property_number;
+
+      /* Create the GNU property note section if needed.  */
+      if (pbfd == NULL)
        {
-         /* If features is set, add GNU_PROPERTY_X86_FEATURE_1_IBT and
-            GNU_PROPERTY_X86_FEATURE_1_SHSTK.  */
-         prop = _bfd_elf_get_property (ebfd,
-                                       GNU_PROPERTY_X86_FEATURE_1_AND,
-                                       4);
-         prop->u.number |= features;
-         prop->pr_kind = property_number;
-
-         /* Create the GNU property note section if needed.  */
-         if (pbfd == NULL)
-           {
-             sec = bfd_make_section_with_flags (ebfd,
-                                                NOTE_GNU_PROPERTY_SECTION_NAME,
-                                                (SEC_ALLOC
-                                                 | SEC_LOAD
-                                                 | SEC_IN_MEMORY
-                                                 | SEC_READONLY
-                                                 | SEC_HAS_CONTENTS
-                                                 | SEC_DATA));
-             if (sec == NULL)
-               info->callbacks->einfo (_("%F: failed to create GNU property section\n"));
+         sec = bfd_make_section_with_flags (ebfd,
+                                            NOTE_GNU_PROPERTY_SECTION_NAME,
+                                            (SEC_ALLOC
+                                             | SEC_LOAD
+                                             | SEC_IN_MEMORY
+                                             | SEC_READONLY
+                                             | SEC_HAS_CONTENTS
+                                             | SEC_DATA));
+         if (sec == NULL)
+           info->callbacks->einfo (_("%F: failed to create GNU property section\n"));
 
-             if (!bfd_set_section_alignment (ebfd, sec,
-                                             ABI_64_P (ebfd) ? 3 : 2))
-               {
+         if (!bfd_set_section_alignment (ebfd, sec,
+                                         ABI_64_P (ebfd) ? 3 : 2))
+           {
 error_alignment:
-                 info->callbacks->einfo (_("%F%A: failed to align section\n"),
-                                         sec);
-               }
-
-             elf_section_type (sec) = SHT_NOTE;
+             info->callbacks->einfo (_("%F%A: failed to align section\n"),
+                                     sec);
            }
-       }
-
-      /* Check GNU_PROPERTY_NO_COPY_ON_PROTECTED.  */
-      for (; pbfd != NULL; pbfd = pbfd->link.next)
-       if (bfd_get_flavour (pbfd) == bfd_target_elf_flavour
-           && (pbfd->flags
-               & (DYNAMIC | BFD_LINKER_CREATED | BFD_PLUGIN)) == 0)
-         {
-           elf_property_list *p;
 
-           /* The property list is sorted in order of type.  */
-           for (p = elf_properties (pbfd); p != NULL; p = p->next)
-             {
-               if (GNU_PROPERTY_NO_COPY_ON_PROTECTED
-                   == p->property.pr_type)
-                 {
-                   /* Clear extern_protected_data if
-                      GNU_PROPERTY_NO_COPY_ON_PROTECTED is
-                      set on any input relocatable file.  */
-                   info->extern_protected_data = FALSE;
-                   break;
-                 }
-               else if (GNU_PROPERTY_NO_COPY_ON_PROTECTED
-                        < p->property.pr_type)
-                 break;
-             }
-         }
+         elf_section_type (sec) = SHT_NOTE;
+       }
     }
 
   pbfd = _bfd_elf_link_setup_gnu_properties (info);
@@ -7830,6 +7841,8 @@ elf_x86_64_special_sections[]=
   elf_x86_64_common_definition
 #define elf_backend_merge_symbol \
   elf_x86_64_merge_symbol
+#define elf_backend_merge_symbol_attribute \
+  elf_x86_64_merge_symbol_attribute
 #define elf_backend_special_sections \
   elf_x86_64_special_sections
 #define elf_backend_additional_program_headers \
index 5efcbd3092c370b725bddca076d14c08435921bd..06b8c251da5d038d92fd99632799b138bd2e0b22 100644 (file)
@@ -1,3 +1,17 @@
+2017-08-26  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/21997
+       * testsuite/ld-i386/i386.exp: Run PR ld/21997 tests.
+       * testsuite/ld-x86-64/x86-64.exp: Likewise.
+       * testsuite/ld-i386/pr21997-1a.S: New file.
+       * testsuite/ld-i386/pr21997-1b.c: Likewise.
+       * testsuite/ld-i386/pr21997-1c.S: Likewise.
+       * testsuite/ld-x86-64/pr21997-1a.S: Likewise.
+       * testsuite/ld-x86-64/pr21997-1a.err: Likewise.
+       * testsuite/ld-x86-64/pr21997-1b.c: Likewise.
+       * testsuite/ld-x86-64/pr21997-1b.err: Likewise.
+       * testsuite/ld-x86-64/pr21997-1c.c: Likewise.
+
 2017-08-24  H.J. Lu  <hongjiu.lu@intel.com>
 
        * testsuite/ld-elf/pr21903c.d: Remove '\' before --.
index c813a80551a4c9a852b7fc92a8e1ad314dc01c9f..bd1561024c5c6976cff35f5a6752bffa25a83273 100644 (file)
@@ -1254,6 +1254,14 @@ if { [isnative]
            {} \
            "pr22001-1.so" \
        ] \
+       [list \
+           "Build pr21997-1.so" \
+           "-shared" \
+           "" \
+           { property-stack.S property-no-copy.S pr21997-1a.S } \
+           {} \
+           "pr21997-1.so" \
+       ] \
     ]
 
     run_ld_link_exec_tests [list \
@@ -1309,6 +1317,49 @@ if { [isnative]
            "pass.out" \
            "-fPIC" \
        ] \
+       [list \
+           "Run pr21997-1" \
+           "$NOPIE_LDFLAGS -Wl,--no-as-needed tmpdir/pr21997-1.so" \
+           "" \
+           { pr21997-1b.c } \
+           "pr21997-1" \
+           "pass.out" \
+           "$NOPIE_CFLAGS" \
+       ] \
+       [list \
+           "Run pr21997-1 (PIC 1)" \
+           "$NOPIE_LDFLAGS -Wl,--no-as-needed tmpdir/pr21997-1.so" \
+           "" \
+           { pr21997-1b.c } \
+           "pr21997-1-pic-1" \
+           "pass.out" \
+           "-fPIC" \
+       ] \
+       [list \
+           "Run pr21997-1 (PIC 2)" \
+           "-pie -Wl,--no-as-needed tmpdir/pr21997-1.so" \
+           "" \
+           { pr21997-1b.c } \
+           "pr21997-1-pic-2" \
+           "pass.out" \
+           "-fPIC" \
+       ] \
+       [list \
+           "Run pr21997-1 (PIE 1)" \
+           "$NOPIE_LDFLAGS -Wl,--no-as-needed tmpdir/pr21997-1.so" \
+           "" \
+           { pr21997-1c.S } \
+           "pr21997-1-pie-1" \
+           "pass.out" \
+       ] \
+       [list \
+           "Run pr21997-1 (PIE 2)" \
+           "-pie -Wl,--no-as-needed tmpdir/pr21997-1.so" \
+           "" \
+           { pr21997-1c.S } \
+           "pr21997-1-pie-2" \
+           "pass.out" \
+       ] \
     ]
 
     if { [at_least_gcc_version 5 0] } {
diff --git a/ld/testsuite/ld-i386/pr21997-1a.S b/ld/testsuite/ld-i386/pr21997-1a.S
new file mode 100644 (file)
index 0000000..aea17f8
--- /dev/null
@@ -0,0 +1,35 @@
+       .text
+       .p2align 4,,15
+       .globl  get_protected
+       .type   get_protected, @function
+get_protected:
+       call    __x86.get_pc_thunk.ax
+       addl    $_GLOBAL_OFFSET_TABLE_, %eax
+       movl    protected@GOTOFF(%eax), %eax
+       ret
+       .size   get_protected, .-get_protected
+       .p2align 4,,15
+       .globl  get_protected_p
+       .type   get_protected_p, @function
+get_protected_p:
+       call    __x86.get_pc_thunk.ax
+       addl    $_GLOBAL_OFFSET_TABLE_, %eax
+       leal    protected@GOTOFF(%eax), %eax
+       ret
+       .size   get_protected_p, .-get_protected_p
+       .protected      protected
+       .globl  protected
+       .data
+       .align 4
+       .type   protected, @object
+       .size   protected, 4
+protected:
+       .long   1
+       .section        .text.__x86.get_pc_thunk.ax,"axG",@progbits,__x86.get_pc_thunk.ax,comdat
+       .globl  __x86.get_pc_thunk.ax
+       .hidden __x86.get_pc_thunk.ax
+       .type   __x86.get_pc_thunk.ax, @function
+__x86.get_pc_thunk.ax:
+       movl    (%esp), %eax
+       ret
+       .section        .note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-i386/pr21997-1b.c b/ld/testsuite/ld-i386/pr21997-1b.c
new file mode 100644 (file)
index 0000000..576362e
--- /dev/null
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+extern int protected;
+extern int get_protected (void);
+extern int* get_protected_p (void);
+
+int
+main ()
+{
+
+  if (protected == get_protected ()
+      && &protected == get_protected_p ())
+    printf ("PASS\n");
+
+  return 0;
+}
diff --git a/ld/testsuite/ld-i386/pr21997-1c.S b/ld/testsuite/ld-i386/pr21997-1c.S
new file mode 100644 (file)
index 0000000..8534877
--- /dev/null
@@ -0,0 +1,51 @@
+       .section        .rodata.str1.1,"aMS",@progbits,1
+.LC0:
+       .string "PASS"
+       .section        .text.startup,"ax",@progbits
+       .p2align 4,,15
+       .globl  main
+       .type   main, @function
+main:
+       leal    4(%esp), %ecx
+       andl    $-16, %esp
+       pushl   -4(%ecx)
+       pushl   %ebp
+       movl    %esp, %ebp
+       pushl   %esi
+       pushl   %ebx
+       pushl   %ecx
+       call    __x86.get_pc_thunk.bx
+       addl    $_GLOBAL_OFFSET_TABLE_, %ebx
+       subl    $12, %esp
+       call    get_protected@PLT
+       movl    protected@GOT(%ebx), %esi
+       cmpl    (%esi), %eax
+       je      .L7
+.L3:
+       leal    -12(%ebp), %esp
+       xorl    %eax, %eax
+       popl    %ecx
+       popl    %ebx
+       popl    %esi
+       popl    %ebp
+       leal    -4(%ecx), %esp
+       ret
+.L7:
+       call    get_protected_p@PLT
+       cmpl    %esi, %eax
+       jne     .L3
+       leal    .LC0@GOTOFF(%ebx), %eax
+       subl    $12, %esp
+       pushl   %eax
+       call    puts@PLT
+       addl    $16, %esp
+       jmp     .L3
+       .size   main, .-main
+       .section        .text.__x86.get_pc_thunk.bx,"axG",@progbits,__x86.get_pc_thunk.bx,comdat
+       .globl  __x86.get_pc_thunk.bx
+       .hidden __x86.get_pc_thunk.bx
+       .type   __x86.get_pc_thunk.bx, @function
+__x86.get_pc_thunk.bx:
+       movl    (%esp), %ebx
+       ret
+       .section        .note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-x86-64/pr21997-1a.S b/ld/testsuite/ld-x86-64/pr21997-1a.S
new file mode 100644 (file)
index 0000000..cab99a9
--- /dev/null
@@ -0,0 +1,24 @@
+       .text
+       .p2align 4,,15
+       .globl  get_protected
+       .type   get_protected, @function
+get_protected:
+       movl    protected(%rip), %eax
+       ret
+       .size   get_protected, .-get_protected
+       .p2align 4,,15
+       .globl  get_protected_p
+       .type   get_protected_p, @function
+get_protected_p:
+       leaq    protected(%rip), %rax
+       ret
+       .size   get_protected_p, .-get_protected_p
+       .protected      protected
+       .globl  protected
+       .data
+       .align 4
+       .type   protected, @object
+       .size   protected, 4
+protected:
+       .long   1
+       .section        .note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-x86-64/pr21997-1a.err b/ld/testsuite/ld-x86-64/pr21997-1a.err
new file mode 100644 (file)
index 0000000..5d663a3
--- /dev/null
@@ -0,0 +1,2 @@
+.*relocation R_X86_64_PC32 against protected symbol `protected' can not be used when making a P(D|I)E object; recompile with -fPIC
+#...
diff --git a/ld/testsuite/ld-x86-64/pr21997-1b.c b/ld/testsuite/ld-x86-64/pr21997-1b.c
new file mode 100644 (file)
index 0000000..ffed117
--- /dev/null
@@ -0,0 +1,13 @@
+#include <stdio.h>
+
+extern int protected;
+extern int get_protected (void);
+
+int
+main ()
+{
+  if (protected == get_protected ())
+    printf ("PASS\n");
+
+  return 0;
+}
diff --git a/ld/testsuite/ld-x86-64/pr21997-1b.err b/ld/testsuite/ld-x86-64/pr21997-1b.err
new file mode 100644 (file)
index 0000000..365de67
--- /dev/null
@@ -0,0 +1,2 @@
+.*relocation R_X86_64_32S against protected symbol `protected' can not be used when making a P(D|I)E object; recompile with -fPIC
+#...
diff --git a/ld/testsuite/ld-x86-64/pr21997-1c.c b/ld/testsuite/ld-x86-64/pr21997-1c.c
new file mode 100644 (file)
index 0000000..6d7b9dc
--- /dev/null
@@ -0,0 +1,13 @@
+#include <stdio.h>
+
+extern int protected;
+extern int* get_protected_p (void);
+
+int
+main ()
+{
+  if (&protected == get_protected_p ())
+    printf ("PASS\n");
+
+  return 0;
+}
index 45e93b2c96bcf3864db68e4ef83f3fe8265146ca..0e018c55773cf37955161ac0fc12ef4886a5f1a9 100644 (file)
@@ -1056,6 +1056,22 @@ if { [isnative] && [which $CC] != 0 } {
            {{error_output "pr22001-1a.err"}} \
            "pr22001-1a" \
        ] \
+       [list \
+           "Build pr21997-1.so" \
+           "-shared" \
+           "" \
+           { property-stack.S property-no-copy.S pr21997-1a.S } \
+           {} \
+           "pr21997-1.so" \
+       ] \
+       [list \
+           "Build pr21997-1a" \
+           "$NOPIE_LDFLAGS -Wl,--no-as-needed tmpdir/pr21997-1.so" \
+           "$NOPIE_CFLAGS" \
+           { pr21997-1b.c } \
+           {{error_output "pr21997-1a.err"}} \
+           "pr21997-1a" \
+       ] \
     ]
 
     if  {[istarget "x86_64-*-linux*-gnux32"]} {
@@ -1069,6 +1085,15 @@ if { [isnative] && [which $CC] != 0 } {
                "pass.out" \
                "$NOPIE_CFLAGS" \
            ] \
+           [list \
+               "Run pr21997-1b" \
+               "$NOPIE_LDFLAGS -Wl,--no-as-needed tmpdir/pr21997-1.so" \
+               "" \
+               { pr21997-1c.c } \
+               "pr21997-1b" \
+               "pass.out" \
+               "$NOPIE_CFLAGS" \
+           ] \
        ]
     } else {
        run_cc_link_tests [list \
@@ -1080,6 +1105,14 @@ if { [isnative] && [which $CC] != 0 } {
                {{error_output "pr22001-1b.err"}} \
                "pr22001-1b" \
            ] \
+           [list \
+               "Build pr21997-1b" \
+               "$NOPIE_LDFLAGS -Wl,--no-as-needed tmpdir/pr21997-1.so" \
+               "$NOPIE_CFLAGS" \
+               { pr21997-1c.c } \
+               {{error_output "pr21997-1b.err"}} \
+               "pr21997-1b" \
+           ] \
        ]
     }
 
@@ -1293,6 +1326,42 @@ if { [isnative] && [which $CC] != 0 } {
            "pass.out" \
            "-fPIC" \
        ] \
+       [list \
+           "Run pr21997-1a (PIC 1)" \
+           "$NOPIE_LDFLAGS -Wl,--no-as-needed tmpdir/pr21997-1.so" \
+           "" \
+           { pr21997-1b.c } \
+           "pr21997-1a-pic-1" \
+           "pass.out" \
+           "-fPIC" \
+       ] \
+       [list \
+           "Run pr21997-1a (PIC 2)" \
+           "-pie -Wl,--no-as-needed tmpdir/pr21997-1.so" \
+           "" \
+           { pr21997-1b.c } \
+           "pr21997-1a-pic-2" \
+           "pass.out" \
+           "-fPIC" \
+       ] \
+       [list \
+           "Run pr21997-1b (PIC 1)" \
+           "$NOPIE_LDFLAGS -Wl,--no-as-needed tmpdir/pr21997-1.so" \
+           "" \
+           { pr21997-1c.c } \
+           "pr21997-1b-pic-1" \
+           "pass.out" \
+           "-fPIC" \
+       ] \
+       [list \
+           "Run pr21997-1b (PIC 2)" \
+           "-pie -Wl,--no-as-needed tmpdir/pr21997-1.so" \
+           "" \
+           { pr21997-1c.c } \
+           "pr21997-1b-pic-2" \
+           "pass.out" \
+           "-fPIC" \
+       ] \
     ]
 
     # Run-time tests which require working ifunc attribute support.
This page took 0.060921 seconds and 4 git commands to generate.