x86: Remove x86 ISA properties with empty bits
[deliverable/binutils-gdb.git] / bfd / elflink.c
index 092edaea261bb4673c0fc836b693119809a6697e..aabbf7f667b9bdac39dc6128be6e5c8527c2b075 100644 (file)
@@ -586,7 +586,12 @@ bfd_elf_link_mark_dynamic_symbol (struct bfd_link_info *info,
       || (d != NULL
          && h->non_elf
          && (*d->match) (&d->head, NULL, h->root.root.string)))
-    h->dynamic = 1;
+    {
+      h->dynamic = 1;
+      /* NB: If a symbol is made dynamic by --dynamic-list, it has
+        non-IR reference.  */
+      h->root.non_ir_ref_dynamic = 1;
+    }
 }
 
 /* Record an assignment to a symbol made by a linker script.  We need
@@ -715,6 +720,7 @@ bfd_elf_record_link_assignment (bfd *output_bfd,
        || h->ref_dynamic
        || bfd_link_dll (info)
        || elf_hash_table (info)->is_relocatable_executable)
+      && !h->forced_local
       && h->dynindx == -1)
     {
       if (! bfd_elf_link_record_dynamic_symbol (info, h))
@@ -947,6 +953,7 @@ _bfd_elf_link_renumber_dynsyms (bfd *output_bfd,
       for (p = output_bfd->sections; p ; p = p->next)
        if ((p->flags & SEC_EXCLUDE) == 0
            && (p->flags & SEC_ALLOC) != 0
+           && elf_hash_table (info)->dynamic_relocs
            && !(*bed->elf_backend_omit_section_dynsym) (output_bfd, info, p))
          {
            ++dynsymcount;
@@ -2216,6 +2223,115 @@ _bfd_elf_link_find_version_dependencies (struct elf_link_hash_entry *h,
   return TRUE;
 }
 
+/* Return TRUE and set *HIDE to TRUE if the versioned symbol is
+   hidden.  Set *T_P to NULL if there is no match.  */
+
+static bfd_boolean
+_bfd_elf_link_hide_versioned_symbol (struct bfd_link_info *info,
+                                    struct elf_link_hash_entry *h,
+                                    const char *version_p,
+                                    struct bfd_elf_version_tree **t_p,
+                                    bfd_boolean *hide)
+{
+  struct bfd_elf_version_tree *t;
+
+  /* Look for the version.  If we find it, it is no longer weak.  */
+  for (t = info->version_info; t != NULL; t = t->next)
+    {
+      if (strcmp (t->name, version_p) == 0)
+       {
+         size_t len;
+         char *alc;
+         struct bfd_elf_version_expr *d;
+
+         len = version_p - h->root.root.string;
+         alc = (char *) bfd_malloc (len);
+         if (alc == NULL)
+           return FALSE;
+         memcpy (alc, h->root.root.string, len - 1);
+         alc[len - 1] = '\0';
+         if (alc[len - 2] == ELF_VER_CHR)
+           alc[len - 2] = '\0';
+
+         h->verinfo.vertree = t;
+         t->used = TRUE;
+         d = NULL;
+
+         if (t->globals.list != NULL)
+           d = (*t->match) (&t->globals, NULL, alc);
+
+         /* See if there is anything to force this symbol to
+            local scope.  */
+         if (d == NULL && t->locals.list != NULL)
+           {
+             d = (*t->match) (&t->locals, NULL, alc);
+             if (d != NULL
+                 && h->dynindx != -1
+                 && ! info->export_dynamic)
+               *hide = TRUE;
+           }
+
+         free (alc);
+         break;
+       }
+    }
+
+  *t_p = t;
+
+  return TRUE;
+}
+
+/* Return TRUE if the symbol H is hidden by version script.  */
+
+bfd_boolean
+_bfd_elf_link_hide_sym_by_version (struct bfd_link_info *info,
+                                  struct elf_link_hash_entry *h)
+{
+  const char *p;
+  bfd_boolean hide = FALSE;
+  const struct elf_backend_data *bed
+    = get_elf_backend_data (info->output_bfd);
+
+  /* Version script only hides symbols defined in regular objects.  */
+  if (!h->def_regular && !ELF_COMMON_DEF_P (h))
+    return TRUE;
+
+  p = strchr (h->root.root.string, ELF_VER_CHR);
+  if (p != NULL && h->verinfo.vertree == NULL)
+    {
+      struct bfd_elf_version_tree *t;
+
+      ++p;
+      if (*p == ELF_VER_CHR)
+       ++p;
+
+      if (*p != '\0'
+         && _bfd_elf_link_hide_versioned_symbol (info, h, p, &t, &hide)
+         && hide)
+       {
+         if (hide)
+           (*bed->elf_backend_hide_symbol) (info, h, TRUE);
+         return TRUE;
+       }
+    }
+
+  /* If we don't have a version for this symbol, see if we can find
+     something.  */
+  if (h->verinfo.vertree == NULL && info->version_info != NULL)
+    {
+      h->verinfo.vertree
+       = bfd_find_version_for_sym (info->version_info,
+                                   h->root.root.string, &hide);
+      if (h->verinfo.vertree != NULL && hide)
+       {
+         (*bed->elf_backend_hide_symbol) (info, h, TRUE);
+         return TRUE;
+       }
+    }
+
+  return FALSE;
+}
+
 /* Figure out appropriate versions for all the symbols.  We may not
    have the version number script until we have read all of the input
    files, so until that point we don't know which symbols should be
@@ -2229,6 +2345,7 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
   const struct elf_backend_data *bed;
   struct elf_info_failed eif;
   char *p;
+  bfd_boolean hide;
 
   sinfo = (struct elf_info_failed *) data;
   info = sinfo->info;
@@ -2248,6 +2365,7 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
   if (!h->def_regular)
     return TRUE;
 
+  hide = FALSE;
   bed = get_elf_backend_data (info->output_bfd);
   p = strchr (h->root.root.string, ELF_VER_CHR);
   if (p != NULL && h->verinfo.vertree == NULL)
@@ -2262,50 +2380,15 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
       if (*p == '\0')
        return TRUE;
 
-      /* Look for the version.  If we find it, it is no longer weak.  */
-      for (t = sinfo->info->version_info; t != NULL; t = t->next)
+      if (!_bfd_elf_link_hide_versioned_symbol (info, h, p, &t, &hide))
        {
-         if (strcmp (t->name, p) == 0)
-           {
-             size_t len;
-             char *alc;
-             struct bfd_elf_version_expr *d;
-
-             len = p - h->root.root.string;
-             alc = (char *) bfd_malloc (len);
-             if (alc == NULL)
-               {
-                 sinfo->failed = TRUE;
-                 return FALSE;
-               }
-             memcpy (alc, h->root.root.string, len - 1);
-             alc[len - 1] = '\0';
-             if (alc[len - 2] == ELF_VER_CHR)
-               alc[len - 2] = '\0';
-
-             h->verinfo.vertree = t;
-             t->used = TRUE;
-             d = NULL;
-
-             if (t->globals.list != NULL)
-               d = (*t->match) (&t->globals, NULL, alc);
-
-             /* See if there is anything to force this symbol to
-                local scope.  */
-             if (d == NULL && t->locals.list != NULL)
-               {
-                 d = (*t->match) (&t->locals, NULL, alc);
-                 if (d != NULL
-                     && h->dynindx != -1
-                     && ! info->export_dynamic)
-                   (*bed->elf_backend_hide_symbol) (info, h, TRUE);
-               }
-
-             free (alc);
-             break;
-           }
+         sinfo->failed = TRUE;
+         return FALSE;
        }
 
+      if (hide)
+       (*bed->elf_backend_hide_symbol) (info, h, TRUE);
+
       /* If we are building an application, we need to create a
         version node for this version.  */
       if (t == NULL && bfd_link_executable (info))
@@ -2361,10 +2444,10 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
 
   /* If we don't have a version for this symbol, see if we can find
      something.  */
-  if (h->verinfo.vertree == NULL && sinfo->info->version_info != NULL)
+  if (!hide
+      && h->verinfo.vertree == NULL
+      && sinfo->info->version_info != NULL)
     {
-      bfd_boolean hide;
-
       h->verinfo.vertree
        = bfd_find_version_for_sym (sinfo->info->version_info,
                                    h->root.root.string, &hide);
@@ -2770,10 +2853,14 @@ _bfd_elf_fix_symbol_flags (struct elf_link_hash_entry *h,
       && (h->root.u.def.section->owner->flags & (DYNAMIC | BFD_PLUGIN)) == 0)
     h->def_regular = 1;
 
+  /* Symbols defined in discarded sections shouldn't be dynamic.  */
+  if (h->root.type == bfd_link_hash_undefined && h->indx == -3)
+    (*bed->elf_backend_hide_symbol) (eif->info, h, TRUE);
+
   /* If a weak undefined symbol has non-default visibility, we also
      hide it from the dynamic linker.  */
-  if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
-      && h->root.type == bfd_link_hash_undefweak)
+  else if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+          && h->root.type == bfd_link_hash_undefweak)
     (*bed->elf_backend_hide_symbol) (eif->info, h, TRUE);
 
   /* A hidden versioned symbol in executable should be forced local if
@@ -3374,6 +3461,9 @@ _bfd_elf_add_dynamic_entry (struct bfd_link_info *info,
   if (! is_elf_hash_table (hash_table))
     return FALSE;
 
+  if (tag == DT_RELA || tag == DT_REL)
+    hash_table->dynamic_relocs = TRUE;
+
   bed = get_elf_backend_data (hash_table->dynobj);
   s = bfd_get_linker_section (hash_table->dynobj, ".dynamic");
   BFD_ASSERT (s != NULL);
@@ -4598,10 +4688,17 @@ error_free_dyn:
              (struct bfd_link_hash_entry **) sym_hash)))
        goto error_free_vers;
 
-      if ((flags & BSF_GNU_UNIQUE)
-         && (abfd->flags & DYNAMIC) == 0
-         && bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour)
-       elf_tdata (info->output_bfd)->has_gnu_symbols |= elf_gnu_symbol_unique;
+      if ((abfd->flags & DYNAMIC) == 0
+         && (bfd_get_flavour (info->output_bfd)
+             == bfd_target_elf_flavour))
+       {
+         if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
+           elf_tdata (info->output_bfd)->has_gnu_symbols
+             |= elf_gnu_symbol_ifunc;
+         if ((flags & BSF_GNU_UNIQUE))
+           elf_tdata (info->output_bfd)->has_gnu_symbols
+             |= elf_gnu_symbol_unique;
+       }
 
       h = *sym_hash;
       /* We need to make sure that indirect symbol dynamic flags are
@@ -6926,7 +7023,7 @@ _bfd_elf_init_2_index_sections (bfd *output_bfd, struct bfd_link_info *info)
   asection *s;
 
   /* Data first, since setting text_index_section changes
-     _bfd_elf_link_omit_section_dynsym.  */
+     _bfd_elf_omit_section_dynsym_default.  */
   for (s = output_bfd->sections; s != NULL; s = s->next)
     if (((s->flags & (SEC_EXCLUDE | SEC_ALLOC | SEC_READONLY)) == SEC_ALLOC)
        && !_bfd_elf_omit_section_dynsym_default (output_bfd, info, s))
@@ -7424,6 +7521,26 @@ _bfd_elf_link_hash_hide_symbol (struct bfd_link_info *info,
     }
 }
 
+/* Hide a symbol. */
+
+void
+_bfd_elf_link_hide_symbol (bfd *output_bfd,
+                          struct bfd_link_info *info,
+                          struct bfd_link_hash_entry *h)
+{
+  if (is_elf_hash_table (info->hash))
+    {
+      const struct elf_backend_data *bed
+       = get_elf_backend_data (output_bfd);
+      struct elf_link_hash_entry *eh
+       = (struct elf_link_hash_entry *) h;
+      bed->elf_backend_hide_symbol (info, eh, TRUE);
+      eh->def_dynamic = 0;
+      eh->ref_dynamic = 0;
+      eh->dynamic_def = 0;
+    }
+}
+
 /* Initialize an ELF linker hash table.  *TABLE has been zeroed by our
    caller.  */
 
@@ -11602,6 +11719,8 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
   std_attrs_section = get_elf_backend_data (abfd)->obj_attrs_section;
   for (o = abfd->sections; o != NULL; o = o->next)
     {
+      bfd_boolean remove = FALSE;
+
       if ((std_attrs_section && strcmp (o->name, std_attrs_section) == 0)
          || strcmp (o->name, ".gnu.attributes") == 0)
        {
@@ -11618,19 +11737,21 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
            }
 
          attr_size = bfd_elf_obj_attr_size (abfd);
+         bfd_set_section_size (abfd, o, attr_size);
+         /* Skip this section later on.  */
+         o->map_head.link_order = NULL;
          if (attr_size)
-           {
-             bfd_set_section_size (abfd, o, attr_size);
-             attr_section = o;
-             /* Skip this section later on.  */
-             o->map_head.link_order = NULL;
-           }
+           attr_section = o;
          else
-           o->flags |= SEC_EXCLUDE;
+           remove = TRUE;
        }
       else if ((o->flags & SEC_GROUP) != 0 && o->size == 0)
        {
          /* Remove empty group section from linker output.  */
+         remove = TRUE;
+       }
+      if (remove)
+       {
          o->flags |= SEC_EXCLUDE;
          bfd_section_list_remove (abfd, o);
          abfd->section_count--;
@@ -12802,20 +12923,31 @@ _bfd_elf_gc_mark_hook (asection *sec,
   return NULL;
 }
 
-/* Return the global debug definition section.  */
+/* Return the debug definition section.  */
 
 static asection *
 elf_gc_mark_debug_section (asection *sec ATTRIBUTE_UNUSED,
                           struct bfd_link_info *info ATTRIBUTE_UNUSED,
                           Elf_Internal_Rela *rel ATTRIBUTE_UNUSED,
                           struct elf_link_hash_entry *h,
-                          Elf_Internal_Sym *sym ATTRIBUTE_UNUSED)
+                          Elf_Internal_Sym *sym)
 {
-  if (h != NULL
-      && (h->root.type == bfd_link_hash_defined
-         || h->root.type == bfd_link_hash_defweak)
-      && (h->root.u.def.section->flags & SEC_DEBUGGING) != 0)
-    return h->root.u.def.section;
+  if (h != NULL)
+    {
+      /* Return the global debug definition section.  */
+      if ((h->root.type == bfd_link_hash_defined
+          || h->root.type == bfd_link_hash_defweak)
+         && (h->root.u.def.section->flags & SEC_DEBUGGING) != 0)
+       return h->root.u.def.section;
+    }
+  else
+    {
+      /* Return the local debug definition section.  */
+      asection *isec = bfd_section_from_elf_index (sec->owner,
+                                                  sym->st_shndx);
+      if ((isec->flags & SEC_DEBUGGING) != 0)
+       return isec;
+    }
 
   return NULL;
 }
This page took 0.030152 seconds and 4 git commands to generate.