* elflink.h (elf_link_add_object_symbols): Don't let a common
[deliverable/binutils-gdb.git] / bfd / elflink.h
index 0ac27da8aa12c1a820453264405192c38c58376b..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.  */
 
@@ -739,6 +741,7 @@ elf_link_add_object_symbols (abfd, info)
        {
          Elf_Internal_Versym iver;
          int vernum;
+         boolean indirect;
          boolean override;
 
          if (ever != NULL)
@@ -848,9 +851,14 @@ 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.  */
@@ -1006,7 +1014,8 @@ elf_link_add_object_symbols (abfd, info)
              && (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)
+             && 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
@@ -2040,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;
 
@@ -2138,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;
@@ -2192,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)
        {
@@ -2238,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
@@ -2602,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
@@ -2638,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))
            {
@@ -2671,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,
@@ -2875,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)
@@ -2939,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
@@ -3024,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)
@@ -3055,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
@@ -3080,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.  */
@@ -4147,7 +4184,6 @@ elf_link_output_extsym (h, data)
   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;
This page took 0.027206 seconds and 4 git commands to generate.