* elf64-ppc.c (ppc64_elf_size_stubs): When determining need for
[deliverable/binutils-gdb.git] / bfd / elflink.c
index 75b8c9699b6501719aa5679395df36927a76776a..a973cd59a342262d137548007e56b32b74770905 100644 (file)
@@ -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))
@@ -252,9 +253,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;
 
@@ -714,7 +719,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
   int bind;
   bfd *oldbfd;
   bfd_boolean newdyn, olddyn, olddef, newdef, newdyncommon, olddyncommon;
-  bfd_boolean newweak, oldweak;
+  bfd_boolean newweak, oldweak, old_asneeded;
 
   *skip = FALSE;
   *override = FALSE;
@@ -844,6 +849,14 @@ _bfd_elf_merge_symbol (bfd *abfd,
   else
     olddef = TRUE;
 
+  /* If the old definition came from an as-needed dynamic library which
+     wasn't found to be needed, treat the sym as undefined.  */
+  old_asneeded = FALSE;
+  if (newdyn
+      && olddyn
+      && (elf_dyn_lib_class (oldbfd) & DYN_AS_NEEDED) != 0)
+    old_asneeded = TRUE;
+
   /* Check TLS symbol.  */
   if ((ELF_ST_TYPE (sym->st_info) == STT_TLS || h->type == STT_TLS)
       && ELF_ST_TYPE (sym->st_info) != h->type)
@@ -1046,6 +1059,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
 
   if (olddyn
       && olddef
+      && !old_asneeded
       && h->root.type == bfd_link_hash_defined
       && h->def_dynamic
       && (h->root.u.def.section->flags & SEC_ALLOC) != 0
@@ -1097,7 +1111,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
 
   if (newdyn
       && newdef
-      && (olddef
+      && ((olddef && !old_asneeded)
          || (h->root.type == bfd_link_hash_common
              && (newweak
                  || ELF_ST_TYPE (sym->st_info) == STT_FUNC))))
@@ -1147,7 +1161,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
      symbol is a function or is weak.  */
 
   flip = NULL;
-  if (! newdyn
+  if ((!newdyn || old_asneeded)
       && (newdef
          || (bfd_is_com_section (sec)
              && (oldweak
@@ -2891,6 +2905,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,
@@ -3340,7 +3356,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 +3434,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 +3515,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)
            {
-             _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)))
+             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)))
+           {
+             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 +3811,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,6 +3946,8 @@ 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);
              if (ret < 0)
@@ -5077,7 +5120,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 +5130,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 +5142,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 +5174,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 +5192,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 +5211,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 +5251,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 +5278,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 +5475,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
@@ -6322,6 +6414,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)
@@ -6736,7 +6830,7 @@ 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
@@ -7204,7 +7298,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;
This page took 0.030057 seconds and 4 git commands to generate.