* bucomm.c (list_supported_targets): Use bfd_target_list.
[deliverable/binutils-gdb.git] / bfd / elflink.h
index 956f6917e422d1bb48fe78d2348697eec527de08..23ea241fbdc10e15c6da3c5b5c4049d81bcb2068 100644 (file)
@@ -899,19 +899,19 @@ elf_merge_symbol (abfd, info, name, sym, psec, pvalue, sym_hash,
 
 /* This function is called to create an indirect symbol from the
    default for the symbol with the default version if needed. The
-   symbol is described by H, NAME, SYM, SEC, VALUE, and OVERRIDE.  We
+   symbol is described by H, NAME, SYM, PSEC, VALUE, and OVERRIDE.  We
    set DYNSYM if the new indirect symbol is dynamic. DT_NEEDED
    indicates if it comes from a DT_NEEDED entry of a shared object.  */
 
 static boolean
-elf_add_default_symbol (abfd, info, h, name, sym, sec, value,
+elf_add_default_symbol (abfd, info, h, name, sym, psec, value,
                        dynsym, override, dt_needed)
      bfd *abfd;
      struct bfd_link_info *info;
      struct elf_link_hash_entry *h;
      const char *name;
      Elf_Internal_Sym *sym;
-     asection **sec;
+     asection **psec;
      bfd_vma *value;
      boolean *dynsym;
      boolean override;
@@ -921,11 +921,13 @@ elf_add_default_symbol (abfd, info, h, name, sym, sec, value,
   boolean size_change_ok;
   char *shortname;
   struct elf_link_hash_entry *hi;
+  struct bfd_link_hash_entry *bh;
   struct elf_backend_data *bed;
   boolean collect;
   boolean dynamic;
   char *p;
   size_t len, shortlen;
+  asection *sec;
 
   /* If this symbol has a version, and it is the default version, we
      create an indirect symbol from the default name to the fully
@@ -970,18 +972,20 @@ elf_add_default_symbol (abfd, info, h, name, sym, sec, value,
      actually going to define an indirect symbol.  */
   type_change_ok = false;
   size_change_ok = false;
-  if (! elf_merge_symbol (abfd, info, shortname, sym, sec, value,
+  sec = *psec;
+  if (! elf_merge_symbol (abfd, info, shortname, sym, &sec, value,
                          &hi, &override, &type_change_ok,
                          &size_change_ok, dt_needed))
     return false;
 
   if (! override)
     {
+      bh = &hi->root;
       if (! (_bfd_generic_link_add_one_symbol
             (info, abfd, shortname, BSF_INDIRECT, bfd_ind_section_ptr,
-             (bfd_vma) 0, name, false, collect,
-             (struct bfd_link_hash_entry **) &hi)))
+             (bfd_vma) 0, name, false, collect, &bh)))
        return false;
+      hi = (struct elf_link_hash_entry *) bh;
     }
   else
     {
@@ -1042,7 +1046,7 @@ elf_add_default_symbol (abfd, info, h, name, sym, sec, value,
                      | ELF_LINK_HASH_DEF_REGULAR)) == 0);
 
       ht = (struct elf_link_hash_entry *) hi->root.u.i.link;
-      (*bed->elf_backend_copy_indirect_symbol) (ht, hi);
+      (*bed->elf_backend_copy_indirect_symbol) (bed, ht, hi);
 
       /* See if the new flags lead us to realize that the symbol must
         be dynamic.  */
@@ -1077,7 +1081,8 @@ elf_add_default_symbol (abfd, info, h, name, sym, sec, value,
   /* Once again, merge with any existing symbol.  */
   type_change_ok = false;
   size_change_ok = false;
-  if (! elf_merge_symbol (abfd, info, shortname, sym, sec, value,
+  sec = *psec;
+  if (! elf_merge_symbol (abfd, info, shortname, sym, &sec, value,
                          &hi, &override, &type_change_ok,
                          &size_change_ok, dt_needed))
     return false;
@@ -1085,18 +1090,22 @@ elf_add_default_symbol (abfd, info, h, name, sym, sec, value,
   if (override)
     {
       /* Here SHORTNAME is a versioned name, so we don't expect to see
-        the type of override we do in the case above.  */
-      (*_bfd_error_handler)
-       (_("%s: warning: unexpected redefinition of `%s'"),
-        bfd_archive_filename (abfd), shortname);
+        the type of override we do in the case above unless it is
+        overridden by a versioned definiton.  */
+      if (hi->root.type != bfd_link_hash_defined
+         && hi->root.type != bfd_link_hash_defweak)
+       (*_bfd_error_handler)
+         (_("%s: warning: unexpected redefinition of indirect versioned symbol `%s'"),
+          bfd_archive_filename (abfd), shortname);
     }
   else
     {
+      bh = &hi->root;
       if (! (_bfd_generic_link_add_one_symbol
             (info, abfd, shortname, BSF_INDIRECT,
-             bfd_ind_section_ptr, (bfd_vma) 0, name, false,
-             collect, (struct bfd_link_hash_entry **) &hi)))
+             bfd_ind_section_ptr, (bfd_vma) 0, name, false, collect, &bh)))
        return false;
+      hi = (struct elf_link_hash_entry *) bh;
 
       /* If there is a duplicate definition somewhere, then HI may not
         point to an indirect symbol.  We will have reported an error
@@ -1110,7 +1119,7 @@ elf_add_default_symbol (abfd, info, h, name, sym, sec, value,
                       & (ELF_LINK_HASH_DEF_DYNAMIC
                          | ELF_LINK_HASH_DEF_REGULAR)) == 0);
 
-         (*bed->elf_backend_copy_indirect_symbol) (h, hi);
+         (*bed->elf_backend_copy_indirect_symbol) (bed, h, hi);
 
          /* See if the new flags lead us to realize that the symbol
             must be dynamic.  */
@@ -2286,6 +2295,7 @@ elf_link_create_dynamic_sections (abfd, info)
   flagword flags;
   register asection *s;
   struct elf_link_hash_entry *h;
+  struct bfd_link_hash_entry *bh;
   struct elf_backend_data *bed;
 
   if (! is_elf_hash_table (info))
@@ -2378,12 +2388,12 @@ elf_link_create_dynamic_sections (abfd, info)
      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 = NULL;
+  bh = NULL;
   if (! (_bfd_generic_link_add_one_symbol
         (info, abfd, "_DYNAMIC", BSF_GLOBAL, s, (bfd_vma) 0,
-         (const char *) NULL, false, get_elf_backend_data (abfd)->collect,
-         (struct bfd_link_hash_entry **) &h)))
+         (const char *) 0, false, get_elf_backend_data (abfd)->collect, &bh)))
     return false;
+  h = (struct elf_link_hash_entry *) bh;
   h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
   h->type = STT_OBJECT;
 
@@ -2448,93 +2458,6 @@ elf_add_dynamic_entry (info, tag, val)
 
   return true;
 }
-
-/* Record a new local dynamic symbol.  */
-
-boolean
-elf_link_record_local_dynamic_symbol (info, input_bfd, input_indx)
-     struct bfd_link_info *info;
-     bfd *input_bfd;
-     long input_indx;
-{
-  struct elf_link_local_dynamic_entry *entry;
-  struct elf_link_hash_table *eht;
-  struct elf_strtab_hash *dynstr;
-  Elf_External_Sym esym;
-  Elf_External_Sym_Shndx eshndx;
-  Elf_External_Sym_Shndx *shndx;
-  unsigned long dynstr_index;
-  char *name;
-  file_ptr pos;
-  bfd_size_type amt;
-
-  if (! is_elf_hash_table (info))
-    return false;
-
-  /* See if the entry exists already.  */
-  for (entry = elf_hash_table (info)->dynlocal; entry ; entry = entry->next)
-    if (entry->input_bfd == input_bfd && entry->input_indx == input_indx)
-      return true;
-
-  entry = (struct elf_link_local_dynamic_entry *)
-    bfd_alloc (input_bfd, (bfd_size_type) sizeof (*entry));
-  if (entry == NULL)
-    return false;
-
-  /* Go find the symbol, so that we can find it's name.  */
-  amt = sizeof (Elf_External_Sym);
-  pos = elf_tdata (input_bfd)->symtab_hdr.sh_offset + input_indx * amt;
-  if (bfd_seek (input_bfd, pos, SEEK_SET) != 0
-      || bfd_bread ((PTR) &esym, amt, input_bfd) != amt)
-    return false;
-  shndx = NULL;
-  if (elf_tdata (input_bfd)->symtab_shndx_hdr.sh_size != 0)
-    {
-      amt = sizeof (Elf_External_Sym_Shndx);
-      pos = elf_tdata (input_bfd)->symtab_shndx_hdr.sh_offset;
-      pos += input_indx * amt;
-      shndx = &eshndx;
-      if (bfd_seek (input_bfd, pos, SEEK_SET) != 0
-         || bfd_bread ((PTR) shndx, amt, input_bfd) != amt)
-       return false;
-    }
-  elf_swap_symbol_in (input_bfd, (const PTR) &esym, (const PTR) shndx,
-                     &entry->isym);
-
-  name = (bfd_elf_string_from_elf_section
-         (input_bfd, elf_tdata (input_bfd)->symtab_hdr.sh_link,
-          entry->isym.st_name));
-
-  dynstr = elf_hash_table (info)->dynstr;
-  if (dynstr == NULL)
-    {
-      /* Create a strtab to hold the dynamic symbol names.  */
-      elf_hash_table (info)->dynstr = dynstr = _bfd_elf_strtab_init ();
-      if (dynstr == NULL)
-       return false;
-    }
-
-  dynstr_index = _bfd_elf_strtab_add (dynstr, name, false);
-  if (dynstr_index == (unsigned long) -1)
-    return false;
-  entry->isym.st_name = dynstr_index;
-
-  eht = elf_hash_table (info);
-
-  entry->next = eht->dynlocal;
-  eht->dynlocal = entry;
-  entry->input_bfd = input_bfd;
-  entry->input_indx = input_indx;
-  eht->dynsymcount++;
-
-  /* Whatever binding the symbol had before, it's now local.  */
-  entry->isym.st_info
-    = ELF_ST_INFO (STB_LOCAL, ELF_ST_TYPE (entry->isym.st_info));
-
-  /* The dynindx will be set at the end of size_dynamic_sections.  */
-
-  return true;
-}
 \f
 /* Read and swap the relocs from the section indicated by SHDR.  This
    may be either a REL or a RELA section.  The relocations are
@@ -3025,6 +2948,9 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
       struct elf_info_failed eif;
       struct elf_link_hash_entry *h;
       asection *dynstr;
+      struct bfd_elf_version_tree *t;
+      struct bfd_elf_version_expr *d;
+      boolean all_defined;
 
       *sinterpptr = bfd_get_section_by_name (dynobj, ".interp");
       BFD_ASSERT (*sinterpptr != NULL || info->shared);
@@ -3105,6 +3031,57 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
            return false;
        }
 
+      /* Make all global versions with definiton.  */
+      for (t = verdefs; t != NULL; t = t->next)
+       for (d = t->globals; d != NULL; d = d->next)
+         if (!d->symver && strchr (d->pattern, '*') == NULL)
+           {
+             const char *verstr, *name;
+             size_t namelen, verlen, newlen;
+             char *newname, *p;
+             struct elf_link_hash_entry *newh;
+
+             name = d->pattern;
+             namelen = strlen (name);
+             verstr = t->name;
+             verlen = strlen (verstr);
+             newlen = namelen + verlen + 3; 
+
+             newname = (char *) bfd_malloc ((bfd_size_type) newlen);
+             if (newname == NULL)
+               return false;
+             memcpy (newname, name, namelen);
+
+             /* Check the hidden versioned definition.  */
+             p = newname + namelen;
+             *p++ = ELF_VER_CHR;
+             memcpy (p, verstr, verlen + 1);
+             newh = elf_link_hash_lookup (elf_hash_table (info),
+                                          newname, false, false,
+                                          false);
+             if (newh == NULL
+                 || (newh->root.type != bfd_link_hash_defined
+                     && newh->root.type != bfd_link_hash_defweak))
+               {
+                 /* Check the default versioned definition.  */
+                 *p++ = ELF_VER_CHR;
+                 memcpy (p, verstr, verlen + 1);
+                 newh = elf_link_hash_lookup (elf_hash_table (info),
+                                              newname, false, false,
+                                              false);
+               }
+             free (newname);
+
+             /* Mark this version if there is a definition and it is
+                not defined in a shared object.  */
+             if (newh != NULL
+                 && ((newh->elf_link_hash_flags
+                      & ELF_LINK_HASH_DEF_DYNAMIC) == 0)
+                 && (newh->root.type == bfd_link_hash_defined
+                     || newh->root.type == bfd_link_hash_defweak))
+               d->symver = 1;
+           }
+
       /* Attach all the symbols to their version information.  */
       asvinfo.output_bfd = output_bfd;
       asvinfo.info = info;
@@ -3117,6 +3094,28 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
       if (asvinfo.failed)
        return false;
 
+      if (!info->allow_undefined_version)
+       {
+         /* Check if all global versions have a definiton.  */
+         all_defined = true;
+         for (t = verdefs; t != NULL; t = t->next)
+           for (d = t->globals; d != NULL; d = d->next)
+             if (!d->symver && !d->script
+                 && strchr (d->pattern, '*') == NULL)
+               {
+                 (*_bfd_error_handler)
+                   (_("%s: undefined version: %s"),
+                    d->pattern, t->name);
+                 all_defined = false;
+               }
+
+         if (!all_defined)
+           {
+             bfd_set_error (bfd_error_bad_value);
+             return false;
+           }
+       }
+
       /* Find all symbols which were defined in a dynamic object and make
         the backend pick a reasonable value for them.  */
       elf_link_hash_traverse (elf_hash_table (info),
@@ -3331,19 +3330,20 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
              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)
                ++cdeps;
 
              /* Add a symbol representing this version.  */
-             h = NULL;
+             bh = NULL;
              if (! (_bfd_generic_link_add_one_symbol
                     (info, dynobj, t->name, BSF_GLOBAL, bfd_abs_section_ptr,
                      (bfd_vma) 0, (const char *) NULL, false,
-                     get_elf_backend_data (dynobj)->collect,
-                     (struct bfd_link_hash_entry **) &h)))
+                     get_elf_backend_data (dynobj)->collect, &bh)))
                return false;
+             h = (struct elf_link_hash_entry *) bh;
              h->elf_link_hash_flags &= ~ ELF_LINK_NON_ELF;
              h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
              h->type = STT_OBJECT;
@@ -3891,9 +3891,12 @@ elf_fix_symbol_flags (h, eif)
     {
       struct elf_link_hash_entry *weakdef;
 
+      weakdef = h->weakdef;
+      if (h->root.type == bfd_link_hash_indirect)
+       h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
       BFD_ASSERT (h->root.type == bfd_link_hash_defined
                  || h->root.type == bfd_link_hash_defweak);
-      weakdef = h->weakdef;
       BFD_ASSERT (weakdef->root.type == bfd_link_hash_defined
                  || weakdef->root.type == bfd_link_hash_defweak);
       BFD_ASSERT (weakdef->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC);
@@ -3908,7 +3911,7 @@ elf_fix_symbol_flags (h, eif)
          struct elf_backend_data *bed;
 
          bed = get_elf_backend_data (elf_hash_table (eif->info)->dynobj);
-         (*bed->elf_backend_copy_indirect_symbol) (weakdef, h);
+         (*bed->elf_backend_copy_indirect_symbol) (bed, weakdef, h);
        }
     }
 
@@ -4345,7 +4348,6 @@ elf_link_assign_sym_version (h, data)
            (_("%s: undefined versioned symbol name %s"),
             bfd_get_filename (sinfo->output_bfd), h->root.root.string);
          bfd_set_error (bfd_error_bad_value);
-       error_return:
          sinfo->failed = true;
          return false;
        }
@@ -4370,18 +4372,34 @@ elf_link_assign_sym_version (h, data)
        {
          if (t->globals != NULL)
            {
+             boolean matched;
+
+             matched = false;
              for (d = t->globals; d != NULL; d = d->next)
                {
                  if ((*d->match) (d, h->root.root.string))
                    {
-                     h->verinfo.vertree = t;
-                     local_ver = NULL;
-                     break;
+                     if (d->symver)
+                       matched = true;
+                     else
+                       {
+                         /* There is a version without definition.  Make
+                            the symbol the default definition for this
+                            version.  */
+                         h->verinfo.vertree = t;
+                         local_ver = NULL;
+                         d->script = 1;
+                         break;
+                       }
                    }
                }
 
              if (d != NULL)
                break;
+             else if (matched)
+               /* There is no undefined version for this symbol. Hide the
+                  default one.  */
+               (*bed->elf_backend_hide_symbol) (info, h, true);
            }
 
          if (t->locals != NULL)
@@ -4414,43 +4432,6 @@ elf_link_assign_sym_version (h, data)
              (*bed->elf_backend_hide_symbol) (info, h, true);
            }
        }
-
-      /* We need to check if a hidden versioned definition should
-        hide the default one.  */
-      if (h->dynindx != -1 && h->verinfo.vertree != NULL)
-       {
-         const char *verstr, *name;
-         size_t namelen, verlen, newlen;
-         char *newname;
-         struct elf_link_hash_entry *newh;
-
-         name = h->root.root.string;
-         namelen = strlen (name);
-         verstr = h->verinfo.vertree->name;
-         verlen = strlen (verstr);
-         newlen = namelen + verlen + 2;
-
-         newname = (char *) bfd_malloc ((bfd_size_type) newlen);
-         if (newname == NULL)
-           goto error_return;
-         memcpy (newname, name, namelen);
-
-         /* Check the hidden versioned definition.  */
-         p = newname + namelen;
-         *p++ = ELF_VER_CHR;
-         memcpy (p, verstr, verlen + 1);
-         newh = elf_link_hash_lookup (elf_hash_table (info), newname,
-                                      false, false, false);
-
-         if (newh
-             && (newh->root.type == bfd_link_hash_defined
-                 || newh->root.type == bfd_link_hash_defweak))
-           /* We found a hidden versioned definition.  Hide the
-              default one.  */
-           (*bed->elf_backend_hide_symbol) (info, h, true);
-
-         free (newname);
-       }
     }
 
   return true;
@@ -6429,7 +6410,7 @@ elf_link_output_extsym (h, data)
 
   /* If we're stripping it, then it was just a dynamic symbol, and
      there's nothing else to do.  */
-  if (strip)
+  if (strip || (input_sec->flags & SEC_EXCLUDE) != 0)
     return true;
 
   h->indx = bfd_get_symcount (finfo->output_bfd);
@@ -6839,20 +6820,12 @@ elf_link_input_bfd (finfo, input_bfd)
                           || h->root.type == bfd_link_hash_defweak)
                          && elf_discarded_section (h->root.u.def.section))
                        {
-#if BFD_VERSION_DATE < 20031005
                          if ((o->flags & SEC_DEBUGGING) != 0)
                            {
-#if BFD_VERSION_DATE > 20021005
-                             (*finfo->info->callbacks->warning)
-                               (finfo->info,
-                                _("warning: relocation against removed section; zeroing"),
-                                NULL, input_bfd, o, rel->r_offset);
-#endif
                              BFD_ASSERT (r_symndx != 0);
                              memset (rel, 0, sizeof (*rel));
                            }
                          else
-#endif
                            {
                              if (! ((*finfo->info->callbacks->undefined_symbol)
                                     (finfo->info, h->root.root.string,
@@ -6868,23 +6841,15 @@ elf_link_input_bfd (finfo, input_bfd)
 
                      if (sec != NULL && elf_discarded_section (sec))
                        {
-#if BFD_VERSION_DATE < 20031005
                          if ((o->flags & SEC_DEBUGGING) != 0
                              || (sec->flags & SEC_LINK_ONCE) != 0)
                            {
-#if BFD_VERSION_DATE > 20021005
-                             (*finfo->info->callbacks->warning)
-                               (finfo->info,
-                                _("warning: relocation against removed section"),
-                                NULL, input_bfd, o, rel->r_offset);
-#endif
                              BFD_ASSERT (r_symndx != 0);
                              rel->r_info
                                = ELF_R_INFO (0, ELF_R_TYPE (rel->r_info));
                              rel->r_addend = 0;
                            }
                          else
-#endif
                            {
                              boolean ok;
                              const char *msg
@@ -8506,7 +8471,12 @@ elf_bfd_discard_info (output_bfd, info)
          if (_bfd_elf_discard_section_eh_frame (abfd, info, eh, ehdr,
                                                 elf_reloc_symbol_deleted_p,
                                                 &cookie))
-           ret = true;
+           {
+             /* Relocs have been edited.  Ensure edited version is
+                used later in relocate_section.  */
+             elf_section_data (eh)->relocs = cookie.rels;
+             ret = true;
+           }
          if (cookie.rels && elf_section_data (eh)->relocs != cookie.rels)
            free (cookie.rels);
        }
This page took 0.028917 seconds and 4 git commands to generate.