* elflink.h (elf_link_add_object_symbols): Don't let a common
[deliverable/binutils-gdb.git] / bfd / elflink.h
index 699b015e7426772218ea35602b6ffa6966a773b6..09a7d8b2252d7998f1ac63001bee441c84cc220d 100644 (file)
@@ -19,12 +19,23 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 /* ELF linker code.  */
 
+/* This struct is used to pass information to routines called via
+   elf_link_hash_traverse which must return failure.  */
+
+struct elf_info_failed
+{
+  boolean failed;
+  struct bfd_link_info *info;
+};
+
 static boolean elf_link_add_object_symbols
   PARAMS ((bfd *, struct bfd_link_info *));
 static boolean elf_link_add_archive_symbols
   PARAMS ((bfd *, struct bfd_link_info *));
 static boolean elf_export_symbol
   PARAMS ((struct elf_link_hash_entry *, PTR));
+static boolean elf_fix_symbol_flags
+  PARAMS ((struct elf_link_hash_entry *, struct elf_info_failed *));
 static boolean elf_adjust_dynamic_symbol
   PARAMS ((struct elf_link_hash_entry *, PTR));
 static boolean elf_link_find_version_dependencies
@@ -36,15 +47,6 @@ static boolean elf_link_assign_sym_version
 static boolean elf_link_renumber_dynsyms
   PARAMS ((struct elf_link_hash_entry *, PTR));
 
-/* This struct is used to pass information to routines called via
-   elf_link_hash_traverse which must return failure.  */
-
-struct elf_info_failed
-{
-  boolean failed;
-  struct bfd_link_info *info;
-};
-
 /* Given an ELF BFD, add symbols to the global hash table as
    appropriate.  */
 
@@ -395,57 +397,8 @@ elf_link_add_object_symbols (abfd, info)
     {
       /* Read in any version definitions.  */
 
-      if (elf_dynverdef (abfd) != 0)
-       {
-         Elf_Internal_Shdr *verdefhdr;
-         bfd_byte *dynver;
-         int i;
-         const Elf_External_Verdef *extverdef;
-         Elf_Internal_Verdef *intverdef;
-
-         verdefhdr = &elf_tdata (abfd)->dynverdef_hdr;
-         elf_tdata (abfd)->verdef =
-           ((Elf_Internal_Verdef *)
-            bfd_zalloc (abfd,
-                        verdefhdr->sh_info * sizeof (Elf_Internal_Verdef)));
-         if (elf_tdata (abfd)->verdef == NULL)
-           goto error_return;
-
-         dynver = (bfd_byte *) bfd_malloc (verdefhdr->sh_size);
-         if (dynver == NULL)
-           goto error_return;
-
-         if (bfd_seek (abfd, verdefhdr->sh_offset, SEEK_SET) != 0
-             || (bfd_read ((PTR) dynver, 1, verdefhdr->sh_size, abfd)
-                 != verdefhdr->sh_size))
-           goto error_return;
-
-         extverdef = (const Elf_External_Verdef *) dynver;
-         intverdef = elf_tdata (abfd)->verdef;
-         for (i = 0; i < verdefhdr->sh_info; i++, intverdef++)
-           {
-             const Elf_External_Verdaux *extverdaux;
-             Elf_Internal_Verdaux intverdaux;
-
-             _bfd_elf_swap_verdef_in (abfd, extverdef, intverdef);
-
-             /* Pick up the name of the version.  */
-             extverdaux = ((const Elf_External_Verdaux *)
-                           ((bfd_byte *) extverdef + intverdef->vd_aux));
-             _bfd_elf_swap_verdaux_in (abfd, extverdaux, &intverdaux);
-
-             intverdef->vd_bfd = abfd;
-             intverdef->vd_nodename =
-               bfd_elf_string_from_elf_section (abfd, verdefhdr->sh_link,
-                                                intverdaux.vda_name);
-
-             extverdef = ((const Elf_External_Verdef *)
-                          ((bfd_byte *) extverdef + intverdef->vd_next));
-           }
-
-         free (dynver);
-         dynver = NULL;
-       }
+      if (! _bfd_elf_slurp_version_tables (abfd))
+       goto error_return;
 
       /* Read in the symbol versions, but don't bother to convert them
          to internal format.  */
@@ -695,6 +648,7 @@ elf_link_add_object_symbols (abfd, info)
       boolean definition;
       boolean size_change_ok, type_change_ok;
       boolean new_weakdef;
+      unsigned int old_alignment;
 
       elf_swap_symbol_in (abfd, esym, &sym);
 
@@ -732,10 +686,10 @@ elf_link_add_object_symbols (abfd, info)
       else if (sym.st_shndx > 0 && sym.st_shndx < SHN_LORESERVE)
        {
          sec = section_from_elf_index (abfd, sym.st_shndx);
-         if (sec != NULL)
-           value -= sec->vma;
-         else
+         if (sec == NULL)
            sec = bfd_abs_section_ptr;
+         else if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0)
+           value -= sec->vma;
        }
       else if (sym.st_shndx == SHN_ABS)
        sec = bfd_abs_section_ptr;
@@ -782,10 +736,12 @@ elf_link_add_object_symbols (abfd, info)
 
       size_change_ok = false;
       type_change_ok = get_elf_backend_data (abfd)->type_change_ok;
+      old_alignment = 0;
       if (info->hash->creator->flavour == bfd_target_elf_flavour)
        {
          Elf_Internal_Versym iver;
          int vernum;
+         boolean indirect;
          boolean override;
 
          if (ever != NULL)
@@ -805,19 +761,58 @@ elf_link_add_object_symbols (abfd, info)
                  int namelen, newlen;
                  char *newname, *p;
 
-                 if (vernum > elf_tdata (abfd)->dynverdef_hdr.sh_info)
+                 if (sym.st_shndx != SHN_UNDEF)
                    {
-                     (*_bfd_error_handler)
-                       ("%s: %s: invalid version %d (max %d)",
-                        abfd->filename, name, vernum,
-                        elf_tdata (abfd)->dynverdef_hdr.sh_info);
-                     bfd_set_error (bfd_error_bad_value);
-                     goto error_return;
+                     if (vernum > elf_tdata (abfd)->dynverdef_hdr.sh_info)
+                       {
+                         (*_bfd_error_handler)
+                           ("%s: %s: invalid version %d (max %d)",
+                            abfd->filename, name, vernum,
+                            elf_tdata (abfd)->dynverdef_hdr.sh_info);
+                         bfd_set_error (bfd_error_bad_value);
+                         goto error_return;
+                       }
+                     else if (vernum > 1)
+                       verstr =
+                         elf_tdata (abfd)->verdef[vernum - 1].vd_nodename;
+                     else
+                       verstr = "";
                    }
-                 else if (vernum > 1)
-                   verstr = elf_tdata (abfd)->verdef[vernum - 1].vd_nodename;
                  else
-                   verstr = "";
+                   {
+                     /* We cannot simply test for the number of
+                        entries in the VERNEED section since the
+                        numbers for the needed versions do not start
+                        at 0.  */
+                     Elf_Internal_Verneed *t;
+
+                     verstr = NULL;
+                     for (t = elf_tdata (abfd)->verref;
+                          t != NULL;
+                          t = t->vn_nextref)
+                       {
+                         Elf_Internal_Vernaux *a;
+
+                         for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
+                           {
+                             if (a->vna_other == vernum)
+                               {
+                                 verstr = a->vna_nodename;
+                                 break;
+                               }
+                           }
+                         if (a != NULL)
+                           break;
+                       }
+                     if (verstr == NULL)
+                       {
+                         (*_bfd_error_handler)
+                           ("%s: %s: invalid needed version %d",
+                            abfd->filename, name, vernum);
+                         bfd_set_error (bfd_error_bad_value);
+                         goto error_return;
+                       }
+                   }
 
                  namelen = strlen (name);
                  newlen = namelen + strlen (verstr) + 2;
@@ -856,9 +851,17 @@ elf_link_add_object_symbols (abfd, info)
          if (h->root.type == bfd_link_hash_new)
            h->elf_link_hash_flags &=~ ELF_LINK_NON_ELF;
 
+         indirect = false;
          while (h->root.type == bfd_link_hash_indirect
                 || h->root.type == bfd_link_hash_warning)
-           h = (struct elf_link_hash_entry *) h->root.u.i.link;
+           {
+             if (h->root.type == bfd_link_hash_indirect)
+               indirect = true;
+             h = (struct elf_link_hash_entry *) h->root.u.i.link;
+           }
+
+         /* FIXME: There are too many cases here, and it's too
+             confusing.  This code needs to be reorganized somehow.  */
 
          /* It's OK to change the type if it used to be a weak
              definition, or if the current definition is weak (and
@@ -875,6 +878,9 @@ elf_link_add_object_symbols (abfd, info)
              || h->root.type == bfd_link_hash_undefined)
            size_change_ok = true;
 
+         if (h->root.type == bfd_link_hash_common)
+           old_alignment = h->root.u.c.p->alignment_power;
+
          override = false;
 
          /* If we are looking at a dynamic object, and this is a
@@ -896,6 +902,39 @@ elf_link_add_object_symbols (abfd, info)
                      && (bind == STB_WEAK
                          || ELF_ST_TYPE (sym.st_info) == STT_FUNC)))
                {
+                 /* In the special case of two symbols which look
+                     like common symbols in a dynamic object, set the
+                     size of the symbol to the larger of the two.  */
+                 if ((sec->flags & SEC_ALLOC) != 0
+                     && (sec->flags & SEC_LOAD) == 0
+                     && sym.st_size > 0
+                     && bind != STB_WEAK
+                     && ELF_ST_TYPE (sym.st_info) != STT_FUNC
+                     && h->root.type == bfd_link_hash_defined
+                     && (h->elf_link_hash_flags
+                         & ELF_LINK_HASH_DEF_DYNAMIC) != 0
+                     && (h->root.u.def.section->owner->flags & DYNAMIC) != 0
+                     && (h->root.u.def.section->flags & SEC_ALLOC) != 0
+                     && (h->root.u.def.section->flags & SEC_LOAD) == 0
+                     && h->size > 0
+                     && h->type != STT_FUNC
+                     && sym.st_size != h->size)
+                   {
+                     /* Note that we only warn if the size is
+                         different.  If the size is the same, then we
+                         simply let the first shared library override
+                         the second.  */
+                     if (! ((*info->callbacks->multiple_common)
+                            (info, h->root.root.string,
+                             h->root.u.def.section->owner,
+                             bfd_link_hash_common,
+                             h->size, abfd, bfd_link_hash_common,
+                             sym.st_size)))
+                       goto error_return;
+                     if (sym.st_size > h->size)
+                       h->size = sym.st_size;
+                   }
+
                  override = true;
                  sec = bfd_und_section_ptr;
                  definition = false;
@@ -905,12 +944,32 @@ elf_link_add_object_symbols (abfd, info)
                }
            }
 
-         /* Similarly, if we are not looking at a dynamic object, and
-            we have a definition, we want to override any definition
-            we may have from a dynamic object.  Symbols from regular
-            files always take precedence over symbols from dynamic
-            objects, even if they are defined after the dynamic
-            object in the link.  */
+         /* If we already have a common symbol, and the symbol in the
+             shared library is in an uninitialized section, then treat
+             the shared library symbol as a common symbol.  This will
+             not always be correct, but it should do little harm.  */
+         if (dynamic
+             && definition
+             && h->root.type == bfd_link_hash_common
+             && (sec->flags & SEC_ALLOC) != 0
+             && (sec->flags & SEC_LOAD) == 0
+             && sym.st_size > 0
+             && bind != STB_WEAK
+             && ELF_ST_TYPE (sym.st_info) != STT_FUNC)
+           {
+             override = true;
+             sec = bfd_com_section_ptr;
+             definition = false;
+             value = sym.st_size;
+             size_change_ok = true;
+           }
+
+         /* If we are not looking at a dynamic object, and we have a
+            definition, we want to override any definition we may
+            have from a dynamic object.  Symbols from regular files
+            always take precedence over symbols from dynamic objects,
+            even if they are defined after the dynamic object in the
+            link.  */
          if (! dynamic
              && (definition
                  || (bfd_is_com_section (sec)
@@ -938,6 +997,50 @@ elf_link_add_object_symbols (abfd, info)
              h->verinfo.vertree = NULL;
            }
 
+         /* If we are not looking at a shared library and we have a
+             common symbol, and the symbol in the shared library is in
+             an uninitialized section, then treat the shared library
+             symbol as a common symbol.  This will not always be
+             correct, but it should do little harm.  Note that the
+             above condition already handled cases in which a common
+             symbol should simply override the definition in the
+             shared library.  */
+         if (! dynamic
+             && ! override
+             && bfd_is_com_section (sec)
+             && h->root.type == bfd_link_hash_defined
+             && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
+             && (h->root.u.def.section->owner->flags & DYNAMIC) != 0
+             && (h->root.u.def.section->flags & SEC_ALLOC) != 0
+             && (h->root.u.def.section->flags & SEC_LOAD) == 0
+             && h->size > 0
+             && h->type != STT_FUNC
+             && ! indirect)
+           {
+             /* It would be best if we could set the hash table entry
+                 to a common symbol, but we don't know what to use for
+                 the section or the alignment.  */
+             if (! ((*info->callbacks->multiple_common)
+                    (info, h->root.root.string,
+                     h->root.u.def.section->owner, bfd_link_hash_common,
+                     h->size, abfd, bfd_link_hash_common, value)))
+               goto error_return;
+
+             if (h->size > value)
+               value = h->size;
+
+             /* FIXME: We no longer know the alignment required by
+                the symbol in the shared library, so we just wind up
+                using the one from the regular object.  */
+
+             override = true;
+             h->root.type = bfd_link_hash_undefined;
+             h->root.u.undef.abfd = h->root.u.def.section->owner;
+             size_change_ok = true;
+             type_change_ok = true;
+             h->verinfo.vertree = NULL;
+           }
+
          if (ever != NULL
              && ! override
              && vernum > 1
@@ -981,10 +1084,16 @@ elf_link_add_object_symbols (abfd, info)
          new_weakdef = true;
        }
 
-      /* Get the alignment of a common symbol.  */
+      /* Set the alignment of a common symbol.  */
       if (sym.st_shndx == SHN_COMMON
          && h->root.type == bfd_link_hash_common)
-       h->root.u.c.p->alignment_power = bfd_log2 (sym.st_value);
+       {
+         unsigned int align;
+
+         align = bfd_log2 (sym.st_value);
+         if (align > old_alignment)
+           h->root.u.c.p->alignment_power = align;
+       }
 
       if (info->hash->creator->flavour == bfd_target_elf_flavour)
        {
@@ -998,16 +1107,21 @@ elf_link_add_object_symbols (abfd, info)
            {
              if (h->size != 0 && h->size != sym.st_size && ! size_change_ok)
                (*_bfd_error_handler)
-                 ("Warning: size of symbol `%s' was %lu, but in %s is %lu; using %lu",
-                  name, (unsigned long) h->size,
-                  bfd_get_filename (abfd), (unsigned long) sym.st_size,
-                  (h->size < sym.st_size
-                   ? (unsigned long) sym.st_size
-                   : (unsigned long) h->size));
-
-             if (h->size < sym.st_size)
-               h->size = sym.st_size;
+                 ("Warning: size of symbol `%s' changed from %lu to %lu in %s",
+                  name, (unsigned long) h->size, (unsigned long) sym.st_size,
+                  bfd_get_filename (abfd));
+
+             h->size = sym.st_size;
            }
+
+         /* If this is a common symbol, then we always want H->SIZE
+             to be the size of the common symbol.  The code just above
+             won't fix the size if a common symbol becomes larger.  We
+             don't warn about a size change here, because that is
+             covered by --warn-common.  */
+         if (h->root.type == bfd_link_hash_common)
+           h->size = h->root.u.c.size;
+
          if (ELF_ST_TYPE (sym.st_info) != STT_NOTYPE
              && (definition || h->type == STT_NOTYPE))
            {
@@ -1469,7 +1583,10 @@ elf_link_add_object_symbols (abfd, info)
          boolean ok;
 
          if ((o->flags & SEC_RELOC) == 0
-             || o->reloc_count == 0)
+             || o->reloc_count == 0
+             || ((info->strip == strip_all || info->strip == strip_debugger)
+                 && (o->flags & SEC_DEBUGGING) != 0)
+             || bfd_is_abs_section (o->output_section))
            continue;
 
          internal_relocs = (NAME(_bfd_elf,link_read_relocs)
@@ -1932,6 +2049,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
   bfd *dynobj;
   struct elf_backend_data *bed;
   bfd_size_type old_dynsymcount;
+  struct elf_assign_sym_version_info asvinfo;
 
   *sinterpptr = NULL;
 
@@ -2030,6 +2148,20 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
            }
        }
 
+      /* Attach all the symbols to their version information.  */
+      asvinfo.output_bfd = output_bfd;
+      asvinfo.info = info;
+      asvinfo.verdefs = verdefs;
+      asvinfo.export_dynamic = export_dynamic;
+      asvinfo.removed_dynamic = false;
+      asvinfo.failed = false;
+
+      elf_link_hash_traverse (elf_hash_table (info),
+                             elf_link_assign_sym_version,
+                             (PTR) &asvinfo);
+      if (asvinfo.failed)
+       return false;
+
       /* Find all symbols which were defined in a dynamic object and make
         the backend pick a reasonable value for them.  */
       eif.failed = false;
@@ -2084,30 +2216,14 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
       size_t i;
       size_t bucketcount = 0;
       Elf_Internal_Sym isym;
-      struct elf_assign_sym_version_info sinfo;
 
       /* Set up the version definition section.  */
       s = bfd_get_section_by_name (dynobj, ".gnu.version_d");
       BFD_ASSERT (s != NULL);
 
-      /* Attach all the symbols to their version information.  This
-         may cause some symbols to be unexported.  */
-      sinfo.output_bfd = output_bfd;
-      sinfo.info = info;
-      sinfo.verdefs = verdefs;
-      sinfo.export_dynamic = export_dynamic;
-      sinfo.removed_dynamic = false;
-      sinfo.failed = false;
-
-      elf_link_hash_traverse (elf_hash_table (info),
-                             elf_link_assign_sym_version,
-                             (PTR) &sinfo);
-      if (sinfo.failed)
-       return false;
-
       /* We may have created additional version definitions if we are
          just linking a regular application.  */
-      verdefs = sinfo.verdefs;
+      verdefs = asvinfo.verdefs;
 
       if (verdefs == NULL)
        {
@@ -2130,7 +2246,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
          Elf_Internal_Verdef def;
          Elf_Internal_Verdaux defaux;
 
-         if (sinfo.removed_dynamic)
+         if (asvinfo.removed_dynamic)
            {
              /* Some dynamic symbols were changed to be local
                 symbols.  In this case, we renumber all of the
@@ -2361,8 +2477,13 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
 
                t->vn_version = VER_NEED_CURRENT;
                t->vn_cnt = caux;
-               indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr,
-                                          t->vn_bfd->filename, true, false);
+               if (elf_dt_name (t->vn_bfd) != NULL)
+                 indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr,
+                                            elf_dt_name (t->vn_bfd),
+                                            true, false);
+               else
+                 indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr,
+                                            t->vn_bfd->filename, true, false);
                if (indx == (bfd_size_type) -1)
                  return false;
                t->vn_file = indx;
@@ -2489,23 +2610,17 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
   return true;
 }
 \f
-/* Make the backend pick a good value for a dynamic symbol.  This is
-   called via elf_link_hash_traverse, and also calls itself
-   recursively.  */
+/* Fix up the flags for a symbol.  This handles various cases which
+   can only be fixed after all the input files are seen.  This is
+   currently called by both adjust_dynamic_symbol and
+   assign_sym_version, which is unnecessary but perhaps more robust in
+   the face of future changes.  */
 
 static boolean
-elf_adjust_dynamic_symbol (h, data)
+elf_fix_symbol_flags (h, eif)
      struct elf_link_hash_entry *h;
-     PTR data;
+     struct elf_info_failed *eif;
 {
-  struct elf_info_failed *eif = (struct elf_info_failed *) data;
-  bfd *dynobj;
-  struct elf_backend_data *bed;
-
-  /* Ignore indirect symbols.  These are added by the versioning code.  */
-  if (h->root.type == bfd_link_hash_indirect)
-    return true;
-
   /* If this symbol was mentioned in a non-ELF file, try to set
      DEF_REGULAR and REF_REGULAR correctly.  This is the only way to
      permit a non-ELF file to correctly refer to a symbol defined in
@@ -2525,8 +2640,9 @@ elf_adjust_dynamic_symbol (h, data)
            h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
        }
 
-      if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
-         || (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0)
+      if (h->dynindx == -1
+         && ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
+             || (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0))
        {
          if (! _bfd_elf_link_record_dynamic_symbol (eif->info, h))
            {
@@ -2558,6 +2674,30 @@ elf_adjust_dynamic_symbol (h, data)
       && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0)
     h->elf_link_hash_flags &=~ ELF_LINK_HASH_NEEDS_PLT;
 
+  return true;
+}
+
+/* Make the backend pick a good value for a dynamic symbol.  This is
+   called via elf_link_hash_traverse, and also calls itself
+   recursively.  */
+
+static boolean
+elf_adjust_dynamic_symbol (h, data)
+     struct elf_link_hash_entry *h;
+     PTR data;
+{
+  struct elf_info_failed *eif = (struct elf_info_failed *) data;
+  bfd *dynobj;
+  struct elf_backend_data *bed;
+
+  /* Ignore indirect symbols.  These are added by the versioning code.  */
+  if (h->root.type == bfd_link_hash_indirect)
+    return true;
+
+  /* Fix the symbol flags.  */
+  if (! elf_fix_symbol_flags (h, eif))
+    return false;
+
   /* If this symbol does not require a PLT entry, and it is not
      defined by a dynamic object, or is not referenced by a regular
      object, ignore it.  We do have to handle a weak defined symbol,
@@ -2702,7 +2842,7 @@ elf_link_find_version_dependencies (h, data)
   /* See if we already know about this version.  */
   for (t = elf_tdata (rinfo->output_bfd)->verref; t != NULL; t = t->vn_nextref)
     {
-      if (t->vn_bfd == h->verinfo.verdef->vd_bfd)
+      if (t->vn_bfd != h->verinfo.verdef->vd_bfd)
        continue;
 
       for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
@@ -2762,8 +2902,19 @@ elf_link_assign_sym_version (h, data)
   struct elf_assign_sym_version_info *sinfo =
     (struct elf_assign_sym_version_info *) data;
   struct bfd_link_info *info = sinfo->info;
+  struct elf_info_failed eif;
   char *p;
 
+  /* Fix the symbol flags.  */
+  eif.failed = false;
+  eif.info = info;
+  if (! elf_fix_symbol_flags (h, &eif))
+    {
+      if (eif.failed)
+       sinfo->failed = true;
+      return false;
+    }
+
   /* We only need version numbers for symbols defined in regular
      objects.  */
   if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
@@ -2826,12 +2977,12 @@ elf_link_assign_sym_version (h, data)
                        {
                          if (h->dynindx != -1
                              && info->shared
-                             && ! sinfo->export_dynamic
-                             && (h->elf_link_hash_flags
-                                 & ELF_LINK_HASH_NEEDS_PLT) == 0)
+                             && ! sinfo->export_dynamic)
                            {
                              sinfo->removed_dynamic = true;
                              h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL;
+                             h->elf_link_hash_flags &=~
+                               ELF_LINK_HASH_NEEDS_PLT;
                              h->dynindx = -1;
                              /* FIXME: The name of the symbol has
                                 already been recorded in the dynamic
@@ -2911,7 +3062,7 @@ elf_link_assign_sym_version (h, data)
       struct bfd_elf_version_expr *d;
 
       /* See if can find what version this symbol is in.  If the
-         symbol is supposed to eb local, then don't actually register
+         symbol is supposed to be local, then don't actually register
          it.  */
       deflt = NULL;
       for (t = sinfo->verdefs; t != NULL; t = t->next)
@@ -2942,12 +3093,11 @@ elf_link_assign_sym_version (h, data)
                      h->verinfo.vertree = t;
                      if (h->dynindx != -1
                          && info->shared
-                         && ! sinfo->export_dynamic
-                         && (h->elf_link_hash_flags
-                             & ELF_LINK_HASH_NEEDS_PLT) == 0)
+                         && ! sinfo->export_dynamic)
                        {
                          sinfo->removed_dynamic = true;
                          h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL;
+                         h->elf_link_hash_flags &=~ ELF_LINK_HASH_NEEDS_PLT;
                          h->dynindx = -1;
                          /* FIXME: The name of the symbol has already
                             been recorded in the dynamic string table
@@ -2967,11 +3117,11 @@ elf_link_assign_sym_version (h, data)
          h->verinfo.vertree = deflt;
          if (h->dynindx != -1
              && info->shared
-             && ! sinfo->export_dynamic
-             && (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) == 0)
+             && ! sinfo->export_dynamic)
            {
              sinfo->removed_dynamic = true;
              h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL;
+             h->elf_link_hash_flags &=~ ELF_LINK_HASH_NEEDS_PLT;
              h->dynindx = -1;
              /* FIXME: The name of the symbol has already been
                 recorded in the dynamic string table section.  */
@@ -4010,13 +4160,30 @@ elf_link_output_extsym (h, data)
              ((struct elf_link_hash_entry *) h->root.u.i.link, data));
     }
 
+  /* Give the processor backend a chance to tweak the symbol value,
+     and also to finish up anything that needs to be done for this
+     symbol.  */
+  if ((h->dynindx != -1
+       || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)
+      && elf_hash_table (finfo->info)->dynamic_sections_created)
+    {
+      struct elf_backend_data *bed;
+
+      bed = get_elf_backend_data (finfo->output_bfd);
+      if (! ((*bed->elf_backend_finish_dynamic_symbol)
+            (finfo->output_bfd, finfo->info, h, &sym)))
+       {
+         eoinfo->failed = true;
+         return false;
+       }
+    }
+
   /* If this symbol should be put in the .dynsym section, then put it
      there now.  We have already know the symbol index.  We also fill
      in the entry in the .hash section.  */
   if (h->dynindx != -1
       && elf_hash_table (finfo->info)->dynamic_sections_created)
     {
-      struct elf_backend_data *bed;
       char *p, *copy;
       const char *name;
       size_t bucketcount;
@@ -4026,17 +4193,6 @@ elf_link_output_extsym (h, data)
 
       sym.st_name = h->dynstr_index;
 
-      /* Give the processor backend a chance to tweak the symbol
-        value, and also to finish up anything that needs to be done
-        for this symbol.  */
-      bed = get_elf_backend_data (finfo->output_bfd);
-      if (! ((*bed->elf_backend_finish_dynamic_symbol)
-            (finfo->output_bfd, finfo->info, h, &sym)))
-       {
-         eoinfo->failed = true;
-         return false;
-       }
-
       elf_swap_symbol_out (finfo->output_bfd, &sym,
                           (PTR) (((Elf_External_Sym *)
                                   finfo->dynsym_sec->contents)
This page took 0.031481 seconds and 4 git commands to generate.