* elflink.c (elf_link_add_object_symbols): Don't add "warning: "
[deliverable/binutils-gdb.git] / bfd / elflink.c
index 08c0aee6f1d880cc6f0823fb865b1b476fe596e3..d7c9ded0b18412dfd401b7bc2dea3d5577f742d1 100644 (file)
@@ -1,5 +1,5 @@
 /* ELF linking support for BFD.
-   Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+   Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
    Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -88,6 +88,7 @@ _bfd_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
       h = (struct elf_link_hash_entry *) bh;
       h->def_regular = 1;
       h->type = STT_OBJECT;
+      h->other = STV_HIDDEN;
 
       if (! info->executable
          && ! bfd_elf_link_record_dynamic_symbol (info, h))
@@ -102,6 +103,25 @@ _bfd_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
   return TRUE;
 }
 \f
+/* Create a strtab to hold the dynamic symbol names.  */
+static bfd_boolean
+_bfd_elf_link_create_dynstrtab (bfd *abfd, struct bfd_link_info *info)
+{
+  struct elf_link_hash_table *hash_table;
+
+  hash_table = elf_hash_table (info);
+  if (hash_table->dynobj == NULL)
+    hash_table->dynobj = abfd;
+
+  if (hash_table->dynstr == NULL)
+    {
+      hash_table->dynstr = _bfd_elf_strtab_init ();
+      if (hash_table->dynstr == NULL)
+       return FALSE;
+    }
+  return TRUE;
+}
+
 /* Create some sections which will be filled in with dynamic linking
    information.  ABFD is an input file which requires dynamic sections
    to be created.  The dynamic sections take up virtual memory space
@@ -124,12 +144,10 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
   if (elf_hash_table (info)->dynamic_sections_created)
     return TRUE;
 
-  /* Make sure that all dynamic sections use the same input BFD.  */
-  if (elf_hash_table (info)->dynobj == NULL)
-    elf_hash_table (info)->dynobj = abfd;
-  else
-    abfd = elf_hash_table (info)->dynobj;
+  if (!_bfd_elf_link_create_dynstrtab (abfd, info))
+    return FALSE;
 
+  abfd = elf_hash_table (info)->dynobj;
   bed = get_elf_backend_data (abfd);
 
   flags = bed->dynamic_sec_flags;
@@ -185,14 +203,6 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
       || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY))
     return FALSE;
 
-  /* Create a strtab to hold the dynamic symbol names.  */
-  if (elf_hash_table (info)->dynstr == NULL)
-    {
-      elf_hash_table (info)->dynstr = _bfd_elf_strtab_init ();
-      if (elf_hash_table (info)->dynstr == NULL)
-       return FALSE;
-    }
-
   s = bfd_make_section (abfd, ".dynamic");
   if (s == NULL
       || ! bfd_set_section_flags (abfd, s, flags)
@@ -200,14 +210,22 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
     return FALSE;
 
   /* The special symbol _DYNAMIC is always set to the start of the
-     .dynamic section.  This call occurs before we have processed the
-     symbols for any dynamic object, so we don't have to worry about
-     overriding a dynamic definition.  We could set _DYNAMIC in a
-     linker script, but we only want to define it if we are, in fact,
-     creating a .dynamic section.  We don't want to define it if there
-     is no .dynamic section, since on some ELF platforms the start up
-     code examines it to decide how to initialize the process.  */
-  bh = NULL;
+     .dynamic section.  We could set _DYNAMIC in a linker script, but we
+     only want to define it if we are, in fact, creating a .dynamic
+     section.  We don't want to define it if there is no .dynamic
+     section, since on some ELF platforms the start up code examines it
+     to decide how to initialize the process.  */
+  h = elf_link_hash_lookup (elf_hash_table (info), "_DYNAMIC",
+                           FALSE, FALSE, FALSE);
+  if (h != NULL)
+    {
+      /* Zap symbol defined in an as-needed lib that wasn't linked.
+        This is a symptom of a larger problem:  Absolute symbols
+        defined in shared libraries can't be overridden, because we
+        lose the link to the bfd which is via the symbol section.  */
+      h->root.type = bfd_link_hash_new;
+    }
+  bh = &h->root;
   if (! (_bfd_generic_link_add_one_symbol
         (info, abfd, "_DYNAMIC", BSF_GLOBAL, s, 0, NULL, FALSE,
          get_elf_backend_data (abfd)->collect, &bh)))
@@ -252,9 +270,13 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
   flags = bed->dynamic_sec_flags;
 
   pltflags = flags;
-  pltflags |= SEC_CODE;
   if (bed->plt_not_loaded)
+    /* We do not clear SEC_ALLOC here because we still want the OS to
+       allocate space for the section; it's just that there's nothing
+       to read in from the object file.  */
     pltflags &= ~ (SEC_CODE | SEC_LOAD | SEC_HAS_CONTENTS);
+  else
+    pltflags |= SEC_ALLOC | SEC_CODE | SEC_LOAD;
   if (bed->plt_readonly)
     pltflags |= SEC_READONLY;
 
@@ -308,16 +330,16 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
        return FALSE;
 
       /* The .rel[a].bss section holds copy relocs.  This section is not
-     normally needed.  We need to create it here, though, so that the
-     linker will map it to an output section.  We can't just create it
-     only if we need it, because we will not know whether we need it
-     until we have seen all the input files, and the first time the
-     main linker code calls BFD after examining all the input files
-     (size_dynamic_sections) the input sections have already been
-     mapped to the output sections.  If the section turns out not to
-     be needed, we can discard it later.  We will never need this
-     section when generating a shared object, since they do not use
-     copy relocs.  */
+        normally needed.  We need to create it here, though, so that the
+        linker will map it to an output section.  We can't just create it
+        only if we need it, because we will not know whether we need it
+        until we have seen all the input files, and the first time the
+        main linker code calls BFD after examining all the input files
+        (size_dynamic_sections) the input sections have already been
+        mapped to the output sections.  If the section turns out not to
+        be needed, we can discard it later.  We will never need this
+        section when generating a shared object, since they do not use
+        copy relocs.  */
       if (! info->shared)
        {
          s = bfd_make_section (abfd,
@@ -418,25 +440,26 @@ bfd_elf_record_link_assignment (bfd *output_bfd ATTRIBUTE_UNUSED,
                                bfd_boolean provide)
 {
   struct elf_link_hash_entry *h;
+  struct elf_link_hash_table *htab;
 
   if (!is_elf_hash_table (info->hash))
     return TRUE;
 
-  h = elf_link_hash_lookup (elf_hash_table (info), name, TRUE, TRUE, FALSE);
+  htab = elf_hash_table (info);
+  h = elf_link_hash_lookup (htab, name, !provide, TRUE, FALSE);
   if (h == NULL)
-    return FALSE;
+    return provide;
 
   /* Since we're defining the symbol, don't let it seem to have not
      been defined.  record_dynamic_symbol and size_dynamic_sections
-     may depend on this.
-     ??? Changing bfd_link_hash_undefined to bfd_link_hash_new (or
-     to bfd_link_hash_undefweak, see linker.c:link_action) runs the risk
-     of some later symbol manipulation setting the symbol back to
-     bfd_link_hash_undefined, and the linker trying to add the symbol to
-     the undefs list twice.  */
+     may depend on this.  */
   if (h->root.type == bfd_link_hash_undefweak
       || h->root.type == bfd_link_hash_undefined)
-    h->root.type = bfd_link_hash_new;
+    {
+      h->root.type = bfd_link_hash_new;
+      if (h->root.u.undef.next != NULL || htab->root.undefs_tail == &h->root)
+       bfd_link_repair_undef_list (&htab->root);
+    }
 
   if (h->root.type == bfd_link_hash_new)
     h->non_elf = 0;
@@ -1147,7 +1170,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
      symbol is a function or is weak.  */
 
   flip = NULL;
-  if (! newdyn
+  if (!newdyn
       && (newdef
          || (bfd_is_com_section (sec)
              && (oldweak
@@ -2465,7 +2488,7 @@ _bfd_elf_dynamic_symbol_p (struct elf_link_hash_entry *h,
       /* Proper resolution for function pointer equality may require
         that these symbols perhaps be resolved dynamically, even though
         we should be resolving them to the current module.  */
-      if (!ignore_protected)
+      if (!ignore_protected || h->type != STT_FUNC)
        binding_stays_local_p = TRUE;
       break;
 
@@ -2528,6 +2551,10 @@ _bfd_elf_symbol_refs_local_p (struct elf_link_hash_entry *h,
   if (ELF_ST_VISIBILITY (h->other) != STV_PROTECTED)
     return TRUE;
 
+  /* STV_PROTECTED non-function symbols are local.  */
+  if (h->type != STT_FUNC)
+    return TRUE;
+
   /* Function pointer equality tests may require that STV_PROTECTED
      symbols be treated as dynamic symbols, even when we know that the
      dynamic linker will resolve them locally.  */
@@ -2728,7 +2755,8 @@ _bfd_elf_add_dynamic_entry (struct bfd_link_info *info,
    1 if a DT_NEEDED tag already exists, and 0 on success.  */
 
 static int
-elf_add_dt_needed_tag (struct bfd_link_info *info,
+elf_add_dt_needed_tag (bfd *abfd,
+                      struct bfd_link_info *info,
                       const char *soname,
                       bfd_boolean do_it)
 {
@@ -2736,6 +2764,9 @@ elf_add_dt_needed_tag (struct bfd_link_info *info,
   bfd_size_type oldsize;
   bfd_size_type strindex;
 
+  if (!_bfd_elf_link_create_dynstrtab (abfd, info))
+    return -1;
+
   hash_table = elf_hash_table (info);
   oldsize = _bfd_elf_strtab_size (hash_table->dynstr);
   strindex = _bfd_elf_strtab_add (hash_table->dynstr, soname, FALSE);
@@ -2750,26 +2781,28 @@ elf_add_dt_needed_tag (struct bfd_link_info *info,
 
       bed = get_elf_backend_data (hash_table->dynobj);
       sdyn = bfd_get_section_by_name (hash_table->dynobj, ".dynamic");
-      BFD_ASSERT (sdyn != NULL);
-
-      for (extdyn = sdyn->contents;
-          extdyn < sdyn->contents + sdyn->size;
-          extdyn += bed->s->sizeof_dyn)
-       {
-         Elf_Internal_Dyn dyn;
+      if (sdyn != NULL)
+       for (extdyn = sdyn->contents;
+            extdyn < sdyn->contents + sdyn->size;
+            extdyn += bed->s->sizeof_dyn)
+         {
+           Elf_Internal_Dyn dyn;
 
-         bed->s->swap_dyn_in (hash_table->dynobj, extdyn, &dyn);
-         if (dyn.d_tag == DT_NEEDED
-             && dyn.d_un.d_val == strindex)
-           {
-             _bfd_elf_strtab_delref (hash_table->dynstr, strindex);
-             return 1;
-           }
-       }
+           bed->s->swap_dyn_in (hash_table->dynobj, extdyn, &dyn);
+           if (dyn.d_tag == DT_NEEDED
+               && dyn.d_un.d_val == strindex)
+             {
+               _bfd_elf_strtab_delref (hash_table->dynstr, strindex);
+               return 1;
+             }
+         }
     }
 
   if (do_it)
     {
+      if (!_bfd_elf_link_create_dynamic_sections (hash_table->dynobj, info))
+       return -1;
+
       if (!_bfd_elf_add_dynamic_entry (info, DT_NEEDED, strindex))
        return -1;
     }
@@ -2780,6 +2813,95 @@ elf_add_dt_needed_tag (struct bfd_link_info *info,
   return 0;
 }
 
+/* Called via elf_link_hash_traverse, elf_smash_syms sets all symbols
+   belonging to NOT_NEEDED to bfd_link_hash_new.  We know there are no
+   references from regular objects to these symbols.
+
+   ??? Should we do something about references from other dynamic
+   obects?  If not, we potentially lose some warnings about undefined
+   symbols.  But how can we recover the initial undefined / undefweak
+   state?  */
+
+struct elf_smash_syms_data
+{
+  bfd *not_needed;
+  struct elf_link_hash_table *htab;
+  bfd_boolean twiddled;
+};
+
+static bfd_boolean
+elf_smash_syms (struct elf_link_hash_entry *h, void *data)
+{
+  struct elf_smash_syms_data *inf = (struct elf_smash_syms_data *) data;
+  struct bfd_link_hash_entry *bh;
+
+  switch (h->root.type)
+    {
+    default:
+    case bfd_link_hash_new:
+      return TRUE;
+
+    case bfd_link_hash_undefined:
+      if (h->root.u.undef.abfd != inf->not_needed)
+       return TRUE;
+      if (h->root.u.undef.weak != NULL
+         && h->root.u.undef.weak != inf->not_needed)
+       {
+         /* Symbol was undefweak in u.undef.weak bfd, and has become
+            undefined in as-needed lib.  Restore weak.  */
+         h->root.type = bfd_link_hash_undefweak;
+         h->root.u.undef.abfd = h->root.u.undef.weak;
+         if (h->root.u.undef.next != NULL
+             || inf->htab->root.undefs_tail == &h->root)
+           inf->twiddled = TRUE;
+         return TRUE;
+       }
+      break;
+
+    case bfd_link_hash_undefweak:
+      if (h->root.u.undef.abfd != inf->not_needed)
+       return TRUE;
+      break;
+
+    case bfd_link_hash_defined:
+    case bfd_link_hash_defweak:
+      if (h->root.u.def.section->owner != inf->not_needed)
+       return TRUE;
+      break;
+
+    case bfd_link_hash_common:
+      if (h->root.u.c.p->section->owner != inf->not_needed)
+       return TRUE;
+      break;
+
+    case bfd_link_hash_warning:
+    case bfd_link_hash_indirect:
+      elf_smash_syms ((struct elf_link_hash_entry *) h->root.u.i.link, data);
+      if (h->root.u.i.link->type != bfd_link_hash_new)
+       return TRUE;
+      if (h->root.u.i.link->u.undef.abfd != inf->not_needed)
+       return TRUE;
+      break;
+    }
+
+  /* There is no way we can undo symbol table state from defined or
+     defweak back to undefined.  */
+  if (h->ref_regular)
+    abort ();
+
+  /* Set sym back to newly created state, but keep undefs list pointer.  */
+  bh = h->root.u.undef.next;
+  if (bh != NULL || inf->htab->root.undefs_tail == &h->root)
+    inf->twiddled = TRUE;
+  (*inf->htab->root.table.newfunc) (&h->root.root,
+                                   &inf->htab->root.table,
+                                   h->root.root.string);
+  h->root.u.undef.next = bh;
+  h->root.u.undef.abfd = inf->not_needed;
+  h->non_elf = 0;
+  return TRUE;
+}
+
 /* Sort symbol by value and section.  */
 static int
 elf_sort_symbol (const void *arg1, const void *arg2)
@@ -2891,6 +3013,8 @@ elf_finalize_dynstr (bfd *output_bfd, struct bfd_link_info *info)
          _bfd_elf_swap_verdef_in (output_bfd, (Elf_External_Verdef *) p,
                                   &def);
          p += sizeof (Elf_External_Verdef);
+         if (def.vd_aux != sizeof (Elf_External_Verdef))
+           continue;
          for (i = 0; i < def.vd_cnt; ++i)
            {
              _bfd_elf_swap_verdaux_in (output_bfd,
@@ -3018,8 +3142,6 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
            {
              char *msg;
              bfd_size_type sz;
-             bfd_size_type prefix_len;
-             const char * gnu_warning_prefix = _("warning: ");
 
              name += sizeof ".gnu.warning." - 1;
 
@@ -3053,16 +3175,14 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
                }
 
              sz = s->size;
-             prefix_len = strlen (gnu_warning_prefix);
-             msg = bfd_alloc (abfd, prefix_len + sz + 1);
+             msg = bfd_alloc (abfd, sz + 1);
              if (msg == NULL)
                goto error_return;
 
-             strcpy (msg, gnu_warning_prefix);
-             if (! bfd_get_section_contents (abfd, s, msg + prefix_len, 0, sz))
+             if (! bfd_get_section_contents (abfd, s, msg, 0, sz))
                goto error_return;
 
-             msg[prefix_len + sz] = '\0';
+             msg[sz] = '\0';
 
              if (! (_bfd_generic_link_add_one_symbol
                     (info, abfd, name, BSF_WARNING, s, 0, msg,
@@ -3262,11 +3382,6 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
         file.  */
       bfd_section_list_clear (abfd);
 
-      /* If this is the first dynamic object found in the link, create
-        the special sections required for dynamic linking.  */
-      if (! _bfd_elf_link_create_dynamic_sections (abfd, info))
-       goto error_return;
-
       /* Find the name to use in a DT_NEEDED entry that refers to this
         object.  If the object has a DT_SONAME entry, we use it.
         Otherwise, if the generic linker stuck something in
@@ -3283,7 +3398,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
         will need to know it.  */
       elf_dt_name (abfd) = soname;
 
-      ret = elf_add_dt_needed_tag (info, soname, add_needed);
+      ret = elf_add_dt_needed_tag (abfd, info, soname, add_needed);
       if (ret < 0)
        goto error_return;
 
@@ -3340,7 +3455,8 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
   if (dynamic)
     {
       /* Read in any version definitions.  */
-      if (! _bfd_elf_slurp_version_tables (abfd))
+      if (!_bfd_elf_slurp_version_tables (abfd,
+                                         info->default_imported_symver))
        goto error_free_sym;
 
       /* Read in the symbol versions, but don't bother to convert them
@@ -3417,6 +3533,12 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
          sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
          if (sec == NULL)
            sec = bfd_abs_section_ptr;
+         else if (sec->kept_section)
+           {
+             /* Symbols from discarded section are undefined.  */
+             sec = bfd_und_section_ptr;
+             isym->st_shndx = SHN_UNDEF;
+           }
          else if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0)
            value -= sec->vma;
        }
@@ -3492,99 +3614,109 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
          unsigned int vernum = 0;
          bfd_boolean skip;
 
-         if (ever != NULL)
+         if (ever == NULL)
+           {
+             if (info->default_imported_symver)
+               /* Use the default symbol version created earlier.  */
+               iver.vs_vers = elf_tdata (abfd)->cverdefs;
+             else
+               iver.vs_vers = 0;
+           }
+         else
+           _bfd_elf_swap_versym_in (abfd, ever, &iver);
+
+         vernum = iver.vs_vers & VERSYM_VERSION;
+
+         /* If this is a hidden symbol, or if it is not version
+            1, we append the version name to the symbol name.
+            However, we do not modify a non-hidden absolute
+            symbol, because it might be the version symbol
+            itself.  FIXME: What if it isn't?  */
+         if ((iver.vs_vers & VERSYM_HIDDEN) != 0
+             || (vernum > 1 && ! bfd_is_abs_section (sec)))
            {
-             _bfd_elf_swap_versym_in (abfd, ever, &iver);
-             vernum = iver.vs_vers & VERSYM_VERSION;
-
-             /* If this is a hidden symbol, or if it is not version
-                1, we append the version name to the symbol name.
-                However, we do not modify a non-hidden absolute
-                symbol, because it might be the version symbol
-                itself.  FIXME: What if it isn't?  */
-             if ((iver.vs_vers & VERSYM_HIDDEN) != 0
-                 || (vernum > 1 && ! bfd_is_abs_section (sec)))
+             const char *verstr;
+             size_t namelen, verlen, newlen;
+             char *newname, *p;
+
+             if (isym->st_shndx != SHN_UNDEF)
                {
-                 const char *verstr;
-                 size_t namelen, verlen, newlen;
-                 char *newname, *p;
+                 if (vernum > elf_tdata (abfd)->cverdefs)
+                   verstr = NULL;
+                 else if (vernum > 1)
+                   verstr =
+                     elf_tdata (abfd)->verdef[vernum - 1].vd_nodename;
+                 else
+                   verstr = "";
 
-                 if (isym->st_shndx != SHN_UNDEF)
+                 if (verstr == NULL)
                    {
-                     if (vernum > elf_tdata (abfd)->dynverdef_hdr.sh_info)
-                       {
-                         (*_bfd_error_handler)
-                           (_("%B: %s: invalid version %u (max %d)"),
-                            abfd, name, vernum,
-                            elf_tdata (abfd)->dynverdef_hdr.sh_info);
-                         bfd_set_error (bfd_error_bad_value);
-                         goto error_free_vers;
-                       }
-                     else if (vernum > 1)
-                       verstr =
-                         elf_tdata (abfd)->verdef[vernum - 1].vd_nodename;
-                     else
-                       verstr = "";
+                     (*_bfd_error_handler)
+                       (_("%B: %s: invalid version %u (max %d)"),
+                        abfd, name, vernum,
+                        elf_tdata (abfd)->cverdefs);
+                     bfd_set_error (bfd_error_bad_value);
+                     goto error_free_vers;
                    }
-                 else
+               }
+             else
+               {
+                 /* 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)
                    {
-                     /* 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;
+                     Elf_Internal_Vernaux *a;
 
-                         for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
+                     for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
+                       {
+                         if (a->vna_other == vernum)
                            {
-                             if (a->vna_other == vernum)
-                               {
-                                 verstr = a->vna_nodename;
-                                 break;
-                               }
+                             verstr = a->vna_nodename;
+                             break;
                            }
-                         if (a != NULL)
-                           break;
-                       }
-                     if (verstr == NULL)
-                       {
-                         (*_bfd_error_handler)
-                           (_("%B: %s: invalid needed version %d"),
-                            abfd, name, vernum);
-                         bfd_set_error (bfd_error_bad_value);
-                         goto error_free_vers;
                        }
+                     if (a != NULL)
+                       break;
+                   }
+                 if (verstr == NULL)
+                   {
+                     (*_bfd_error_handler)
+                       (_("%B: %s: invalid needed version %d"),
+                        abfd, name, vernum);
+                     bfd_set_error (bfd_error_bad_value);
+                     goto error_free_vers;
                    }
+               }
 
-                 namelen = strlen (name);
-                 verlen = strlen (verstr);
-                 newlen = namelen + verlen + 2;
-                 if ((iver.vs_vers & VERSYM_HIDDEN) == 0
-                     && isym->st_shndx != SHN_UNDEF)
-                   ++newlen;
+             namelen = strlen (name);
+             verlen = strlen (verstr);
+             newlen = namelen + verlen + 2;
+             if ((iver.vs_vers & VERSYM_HIDDEN) == 0
+                 && isym->st_shndx != SHN_UNDEF)
+               ++newlen;
 
-                 newname = bfd_alloc (abfd, newlen);
-                 if (newname == NULL)
-                   goto error_free_vers;
-                 memcpy (newname, name, namelen);
-                 p = newname + namelen;
-                 *p++ = ELF_VER_CHR;
-                 /* If this is a defined non-hidden version symbol,
-                    we add another @ to the name.  This indicates the
-                    default version of the symbol.  */
-                 if ((iver.vs_vers & VERSYM_HIDDEN) == 0
-                     && isym->st_shndx != SHN_UNDEF)
-                   *p++ = ELF_VER_CHR;
-                 memcpy (p, verstr, verlen + 1);
+             newname = bfd_alloc (abfd, newlen);
+             if (newname == NULL)
+               goto error_free_vers;
+             memcpy (newname, name, namelen);
+             p = newname + namelen;
+             *p++ = ELF_VER_CHR;
+             /* If this is a defined non-hidden version symbol,
+                we add another @ to the name.  This indicates the
+                default version of the symbol.  */
+             if ((iver.vs_vers & VERSYM_HIDDEN) == 0
+                 && isym->st_shndx != SHN_UNDEF)
+               *p++ = ELF_VER_CHR;
+             memcpy (p, verstr, verlen + 1);
 
-                 name = newname;
-               }
+             name = newname;
            }
 
          if (!_bfd_elf_merge_symbol (abfd, info, name, isym, &sec, &value,
@@ -3778,6 +3910,14 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
            (*bed->elf_backend_merge_symbol_attribute) (h, isym, definition,
                                                        dynamic);
 
+         /* If this symbol has default visibility and the user has requested
+            we not re-export it, then mark it as hidden.  */
+         if (definition && !dynamic
+             && (abfd->no_export
+                 || (abfd->my_archive && abfd->my_archive->no_export))
+             && ELF_ST_VISIBILITY (isym->st_other) != STV_INTERNAL)
+           isym->st_other = STV_HIDDEN | (isym->st_other & ~ ELF_ST_VISIBILITY (-1));
+
          if (isym->st_other != 0 && !dynamic)
            {
              unsigned char hvis, symvis, other, nvis;
@@ -3905,8 +4045,10 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
                  goto error_free_vers;
                }
 
+             elf_dyn_lib_class (abfd) &= ~DYN_AS_NEEDED;
+
              add_needed = TRUE;
-             ret = elf_add_dt_needed_tag (info, soname, add_needed);
+             ret = elf_add_dt_needed_tag (abfd, info, soname, add_needed);
              if (ret < 0)
                goto error_free_vers;
 
@@ -3974,6 +4116,21 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
     free (isymbuf);
   isymbuf = NULL;
 
+  if (!add_needed
+      && (elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0)
+    {
+      /* Remove symbols defined in an as-needed shared lib that wasn't
+        needed.  */
+      struct elf_smash_syms_data inf;
+      inf.not_needed = abfd;
+      inf.htab = hash_table;
+      inf.twiddled = FALSE;
+      elf_link_hash_traverse (hash_table, elf_smash_syms, &inf);
+      if (inf.twiddled)
+       bfd_link_repair_undef_list (&hash_table->root);
+      weaks = NULL;
+    }
+
   /* Now set the weakdefs field correctly for all the weak defined
      symbols we found.  The only way to do this is to search all the
      symbols.  Since we only need the information for non functions in
@@ -4206,7 +4363,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
        }
     }
 
-  if (is_elf_hash_table (hash_table))
+  if (is_elf_hash_table (hash_table) && add_needed)
     {
       /* Add this bfd to the loaded list.  */
       struct elf_link_loaded_list *n;
@@ -5077,7 +5234,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
       if (verdefs != NULL && verdefs->vernum == 0)
        verdefs = verdefs->next;
 
-      if (verdefs == NULL)
+      if (verdefs == NULL && !info->create_default_symver)
        _bfd_strip_section_from_output (info, s);
       else
        {
@@ -5087,6 +5244,9 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
          bfd_byte *p;
          Elf_Internal_Verdef def;
          Elf_Internal_Verdaux defaux;
+         struct bfd_link_hash_entry *bh;
+         struct elf_link_hash_entry *h;
+         const char *name;
 
          cdefs = 0;
          size = 0;
@@ -5096,6 +5256,13 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
          size += sizeof (Elf_External_Verdaux);
          ++cdefs;
 
+         /* Make space for the default version.  */
+         if (info->create_default_symver)
+           {
+             size += sizeof (Elf_External_Verdef);
+             ++cdefs;
+           }
+
          for (t = verdefs; t != NULL; t = t->next)
            {
              struct bfd_elf_version_deps *n;
@@ -5121,9 +5288,17 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
          def.vd_flags = VER_FLG_BASE;
          def.vd_ndx = 1;
          def.vd_cnt = 1;
-         def.vd_aux = sizeof (Elf_External_Verdef);
-         def.vd_next = (sizeof (Elf_External_Verdef)
-                        + sizeof (Elf_External_Verdaux));
+         if (info->create_default_symver)
+           {
+             def.vd_aux = 2 * sizeof (Elf_External_Verdef);
+             def.vd_next = sizeof (Elf_External_Verdef);
+           }
+         else
+           {
+             def.vd_aux = sizeof (Elf_External_Verdef);
+             def.vd_next = (sizeof (Elf_External_Verdef)
+                            + sizeof (Elf_External_Verdaux));
+           }
 
          if (soname_indx != (bfd_size_type) -1)
            {
@@ -5131,10 +5306,10 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
                                      soname_indx);
              def.vd_hash = bfd_elf_hash (soname);
              defaux.vda_name = soname_indx;
+             name = soname;
            }
          else
            {
-             const char *name;
              bfd_size_type indx;
 
              name = basename (output_bfd->filename);
@@ -5150,6 +5325,38 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
          _bfd_elf_swap_verdef_out (output_bfd, &def,
                                    (Elf_External_Verdef *) p);
          p += sizeof (Elf_External_Verdef);
+         if (info->create_default_symver)
+           {
+             /* Add a symbol representing this version.  */
+             bh = NULL;
+             if (! (_bfd_generic_link_add_one_symbol
+                    (info, dynobj, name, BSF_GLOBAL, bfd_abs_section_ptr,
+                     0, NULL, FALSE,
+                     get_elf_backend_data (dynobj)->collect, &bh)))
+               return FALSE;
+             h = (struct elf_link_hash_entry *) bh;
+             h->non_elf = 0;
+             h->def_regular = 1;
+             h->type = STT_OBJECT;
+             h->verinfo.vertree = NULL;
+
+             if (! bfd_elf_link_record_dynamic_symbol (info, h))
+               return FALSE;
+
+             /* Create a duplicate of the base version with the same
+                aux block, but different flags.  */
+             def.vd_flags = 0;
+             def.vd_ndx = 2;
+             def.vd_aux = sizeof (Elf_External_Verdef);
+             if (verdefs)
+               def.vd_next = (sizeof (Elf_External_Verdef)
+                              + sizeof (Elf_External_Verdaux));
+             else
+               def.vd_next = 0;
+             _bfd_elf_swap_verdef_out (output_bfd, &def,
+                                       (Elf_External_Verdef *) p);
+             p += sizeof (Elf_External_Verdef);
+           }
          _bfd_elf_swap_verdaux_out (output_bfd, &defaux,
                                     (Elf_External_Verdaux *) p);
          p += sizeof (Elf_External_Verdaux);
@@ -5158,8 +5365,6 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
            {
              unsigned int cdeps;
              struct bfd_elf_version_deps *n;
-             struct elf_link_hash_entry *h;
-             struct bfd_link_hash_entry *bh;
 
              cdeps = 0;
              for (n = t->deps; n != NULL; n = n->next)
@@ -5187,7 +5392,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
                  && t->locals.list == NULL
                  && ! t->used)
                def.vd_flags |= VER_FLG_WEAK;
-             def.vd_ndx = t->vernum + 1;
+             def.vd_ndx = t->vernum + (info->create_default_symver ? 2 : 1);
              def.vd_cnt = cdeps + 1;
              def.vd_hash = bfd_elf_hash (t->name);
              def.vd_aux = sizeof (Elf_External_Verdef);
@@ -5384,7 +5589,8 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
       s = bfd_get_section_by_name (dynobj, ".gnu.version");
       BFD_ASSERT (s != NULL);
       if (dynsymcount == 0
-         || (verdefs == NULL && elf_tdata (output_bfd)->verref == NULL))
+         || (verdefs == NULL && elf_tdata (output_bfd)->verref == NULL
+             && !info->create_default_symver))
        {
          _bfd_strip_section_from_output (info, s);
          /* The DYNSYMCOUNT might have changed if we were going to
@@ -6105,7 +6311,8 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data)
   if (h->indx == -2)
     strip = FALSE;
   else if ((h->def_dynamic
-           || h->ref_dynamic)
+           || h->ref_dynamic
+           || h->root.type == bfd_link_hash_new)
           && !h->def_regular
           && !h->ref_regular)
     strip = TRUE;
@@ -6322,6 +6529,8 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data)
                iversym.vs_vers = 1;
              else
                iversym.vs_vers = h->verinfo.vertree->vernum + 1;
+             if (finfo->info->create_default_symver)
+               iversym.vs_vers++;
            }
 
          if (h->hidden)
@@ -6374,30 +6583,40 @@ elf_section_ignore_discarded_relocs (asection *sec)
   return FALSE;
 }
 
-/* Return TRUE if we should complain about a reloc in SEC against a
-   symbol defined in a discarded section.  */
-
-static bfd_boolean
-elf_section_complain_discarded (asection *sec)
+enum action_discarded
+  {
+    COMPLAIN = 1,
+    PRETEND = 2
+  };
+
+/* Return a mask saying how ld should treat relocations in SEC against
+   symbols defined in discarded sections.  If this function returns
+   COMPLAIN set, ld will issue a warning message.  If this function
+   returns PRETEND set, and the discarded section was link-once and the
+   same size as the kept link-once section, ld will pretend that the
+   symbol was actually defined in the kept section.  Otherwise ld will
+   zero the reloc (at least that is the intent, but some cooperation by
+   the target dependent code is needed, particularly for REL targets).  */
+
+static unsigned int
+elf_action_discarded (asection *sec)
 {
-  if (strncmp (".stab", sec->name, 5) == 0
-      && (!sec->name[5] ||
-         (sec->name[5] == '.' && ISDIGIT (sec->name[6]))))
-    return FALSE;
+  if (sec->flags & SEC_DEBUGGING)
+    return PRETEND;
 
   if (strcmp (".eh_frame", sec->name) == 0)
-    return FALSE;
+    return 0;
 
   if (strcmp (".gcc_except_table", sec->name) == 0)
-    return FALSE;
+    return 0;
 
   if (strcmp (".PARISC.unwind", sec->name) == 0)
-    return FALSE;
+    return 0;
 
   if (strcmp (".fixup", sec->name) == 0)
-    return FALSE;
+    return 0;
 
-  return TRUE;
+  return COMPLAIN | PRETEND;
 }
 
 /* Find a match between a section and a member of a section group.  */
@@ -6692,7 +6911,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
          if (!elf_section_ignore_discarded_relocs (o))
            {
              Elf_Internal_Rela *rel, *relend;
-             bfd_boolean complain = elf_section_complain_discarded (o);
+             unsigned int action = elf_action_discarded (o);
 
              rel = internal_relocs;
              relend = rel + o->reloc_count * bed->s->int_rels_per_ext_rel;
@@ -6726,51 +6945,17 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
                    {
                      Elf_Internal_Sym *sym = isymbuf + r_symndx;
                      ps = &finfo->sections[r_symndx];
-                     sym_name = bfd_elf_local_sym_name (input_bfd, sym);
+                     sym_name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym);
                    }
 
                  /* Complain if the definition comes from a
                     discarded section.  */
                  if ((sec = *ps) != NULL && elf_discarded_section (sec))
                    {
-                     if ((o->flags & SEC_DEBUGGING) != 0)
-                       {
-                         BFD_ASSERT (r_symndx != 0);
-
-                         /* Try to preserve debug information.
-                            FIXME: This is quite broken.  Modifying
-                            the symbol here means we will be changing
-                            all uses of the symbol, not just those in
-                            debug sections.  The only thing that makes
-                            this half reasonable is that debug sections
-                            tend to come after other sections.  Of
-                            course, that doesn't help with globals.
-                            ??? All link-once sections of the same name
-                            ought to define the same set of symbols, so
-                            it would seem that globals ought to always
-                            be defined in the kept section.  */
-                         if (sec->kept_section != NULL)
-                           {
-                             asection *member;
+                     asection *kept;
 
-                             /* Check if it is a linkonce section or
-                                member of a comdat group.  */
-                             if (elf_sec_group (sec) == NULL
-                                 && sec->size == sec->kept_section->size)
-                               {
-                                 *ps = sec->kept_section;
-                                 continue;
-                               }
-                             else if (elf_sec_group (sec) != NULL
-                                      && (member = match_group_member (sec, sec->kept_section))
-                                      && sec->size == member->size)
-                               {
-                                 *ps = member;
-                                 continue;
-                               }
-                           }
-                       }
-                     else if (complain)
+                     BFD_ASSERT (r_symndx != 0);
+                     if (action & COMPLAIN)
                        {
                          (*_bfd_error_handler)
                            (_("`%s' referenced in section `%A' of %B: "
@@ -6778,6 +6963,30 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
                             o, input_bfd, sec, sec->owner, sym_name);
                        }
 
+                     /* Try to do the best we can to support buggy old
+                        versions of gcc.  If we've warned, or this is
+                        debugging info, pretend that the symbol is
+                        really defined in the kept linkonce section.
+                        FIXME: This is quite broken.  Modifying the
+                        symbol here means we will be changing all later
+                        uses of the symbol, not just in this section.
+                        The only thing that makes this half reasonable
+                        is that we warn in non-debug sections, and
+                        debug sections tend to come after other
+                        sections.  */
+                     kept = sec->kept_section;
+                     if (kept != NULL && (action & PRETEND))
+                       {
+                         if (elf_sec_group (sec) != NULL)
+                           kept = match_group_member (sec, kept);
+                         if (kept != NULL
+                             && sec->size == kept->size)
+                           {
+                             *ps = kept;
+                             continue;
+                           }
+                       }
+
                      /* Remove the symbol reference from the reloc, but
                         don't kill the reloc completely.  This is so that
                         a zero value will be written into the section,
@@ -7204,7 +7413,8 @@ elf_reloc_link_order (bfd *output_bfd,
          else
            sym_name = link_order->u.reloc.p->u.name;
          if (! ((*info->callbacks->reloc_overflow)
-                (info, sym_name, howto->name, addend, NULL, NULL, 0)))
+                (info, NULL, sym_name, howto->name, addend, NULL,
+                 NULL, (bfd_vma) 0)))
            {
              free (buf);
              return FALSE;
@@ -7720,22 +7930,6 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
        goto error_return;
     }
 
-#if 0
-  /* Some standard ELF linkers do this, but we don't because it causes
-     bootstrap comparison failures.  */
-  /* Output a file symbol for the output file as the second symbol.
-     We output this even if we are discarding local symbols, although
-     I'm not sure if this is correct.  */
-  elfsym.st_value = 0;
-  elfsym.st_size = 0;
-  elfsym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FILE);
-  elfsym.st_other = 0;
-  elfsym.st_shndx = SHN_ABS;
-  if (! elf_link_output_sym (&finfo, bfd_get_filename (abfd),
-                            &elfsym, bfd_abs_section_ptr, NULL))
-    goto error_return;
-#endif
-
   /* Output a symbol for each section.  We output these even if we are
      discarding local symbols, since they are used for relocs.  These
      symbols have no names.  We store the index of each one in the
@@ -9268,88 +9462,11 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
   return ret;
 }
 
-struct already_linked_section
-{
-  asection *sec;
-  asection *linked;
-};
-
-/* Check if the member of a single member comdat group matches a
-   linkonce section and vice versa.  */
-static bfd_boolean
-try_match_symbols_in_sections
-  (struct bfd_section_already_linked_hash_entry *h, void *info)
-{
-  struct bfd_section_already_linked *l;
-  struct already_linked_section *s
-    = (struct already_linked_section *) info;
-
-  if (elf_sec_group (s->sec) == NULL)
-    {
-      /* It is a linkonce section. Try to match it with the member of a
-        single member comdat group. */
-      for (l = h->entry; l != NULL; l = l->next)
-       if ((l->sec->flags & SEC_GROUP))
-         {
-           asection *first = elf_next_in_group (l->sec);
-
-           if (first != NULL
-               && elf_next_in_group (first) == first
-               && bfd_elf_match_symbols_in_sections (first, s->sec))
-             {
-               s->linked = first;
-               return FALSE;
-             }
-         }
-    }
-  else
-    {
-      /* It is the member of a single member comdat group. Try to match
-        it with a linkonce section.  */
-      for (l = h->entry; l != NULL; l = l->next)
-       if ((l->sec->flags & SEC_GROUP) == 0
-           && bfd_coff_get_comdat_section (l->sec->owner, l->sec) == NULL
-           && bfd_elf_match_symbols_in_sections (l->sec, s->sec))
-         {
-           s->linked = l->sec;
-           return FALSE;
-         }
-    }
-
-  return TRUE;
-}
-
-static bfd_boolean
-already_linked (asection *sec, asection *group)
-{
-  struct already_linked_section result;
-
-  result.sec = sec;
-  result.linked = NULL;
-
-  bfd_section_already_linked_table_traverse
-    (try_match_symbols_in_sections, &result);
-
-  if (result.linked)
-    {
-      sec->output_section = bfd_abs_section_ptr;
-      sec->kept_section = result.linked;
-
-      /* Also discard the group section.  */
-      if (group)
-       group->output_section = bfd_abs_section_ptr;
-
-      return TRUE;
-    }
-
-  return FALSE;
-}
-
 void
 _bfd_elf_section_already_linked (bfd *abfd, struct bfd_section * sec)
 {
   flagword flags;
-  const char *name;
+  const char *name, *p;
   struct bfd_section_already_linked *l;
   struct bfd_section_already_linked_hash_entry *already_linked_list;
   asection *group;
@@ -9399,7 +9516,13 @@ _bfd_elf_section_already_linked (bfd *abfd, struct bfd_section * sec)
 
   name = bfd_get_section_name (abfd, sec);
 
-  already_linked_list = bfd_section_already_linked_table_lookup (name);
+  if (strncmp (name, ".gnu.linkonce.", sizeof (".gnu.linkonce.") - 1) == 0
+      && (p = strchr (name + sizeof (".gnu.linkonce.") - 1, '.')) != NULL)
+    p++;
+  else
+    p = name;
+
+  already_linked_list = bfd_section_already_linked_table_lookup (p);
 
   for (l = already_linked_list->entry; l != NULL; l = l->next)
     {
@@ -9409,10 +9532,11 @@ _bfd_elf_section_already_linked (bfd *abfd, struct bfd_section * sec)
         a linkonce section with a linkonce section, and ignore comdat
         section.  */
       if ((flags & SEC_GROUP) == (l->sec->flags & SEC_GROUP)
+         && strcmp (name, l->sec->name) == 0
          && bfd_coff_get_comdat_section (l->sec->owner, l->sec) == NULL)
        {
          /* The section has already been linked.  See if we should
-             issue a warning.  */
+            issue a warning.  */
          switch (flags & SEC_LINK_DUPLICATES)
            {
            default:
@@ -9501,15 +9625,39 @@ _bfd_elf_section_already_linked (bfd *abfd, struct bfd_section * sec)
         section. We only record the discarded comdat group. Otherwise
         the undiscarded group will be discarded incorrectly later since
         itself has been recorded.  */
-      if (! already_linked (elf_next_in_group (sec), group))
+      for (l = already_linked_list->entry; l != NULL; l = l->next)
+       if ((l->sec->flags & SEC_GROUP) == 0
+           && bfd_coff_get_comdat_section (l->sec->owner, l->sec) == NULL
+           && bfd_elf_match_symbols_in_sections (l->sec,
+                                                 elf_next_in_group (sec)))
+         {
+           elf_next_in_group (sec)->output_section = bfd_abs_section_ptr;
+           elf_next_in_group (sec)->kept_section = l->sec;
+           group->output_section = bfd_abs_section_ptr;
+           break;
+         }
+      if (l == NULL)
        return;
     }
   else
     /* There is no direct match. But for linkonce section, we should
        check if there is a match with comdat group member. We always
        record the linkonce section, discarded or not.  */
-    already_linked (sec, group);
-  
+    for (l = already_linked_list->entry; l != NULL; l = l->next)
+      if (l->sec->flags & SEC_GROUP)
+       {
+         asection *first = elf_next_in_group (l->sec);
+
+         if (first != NULL
+             && elf_next_in_group (first) == first
+             && bfd_elf_match_symbols_in_sections (first, sec))
+           {
+             sec->output_section = bfd_abs_section_ptr;
+             sec->kept_section = l->sec;
+             break;
+           }
+       }
+
   /* This is the first section with this name.  Record it.  */
   bfd_section_already_linked_table_insert (already_linked_list, sec);
 }
This page took 0.040872 seconds and 4 git commands to generate.