Add prototypes for static functions.
[binutils-gdb.git] / bfd / elflink.h
index 2cbd80a8485b7397d239bc429dacc6aa8d7b7d7a..cbc18d94b7d8560abaf604cac51ce6203d35e804 100644 (file)
@@ -1,5 +1,5 @@
 /* ELF linker support.
-   Copyright 1995, 1996, 1997 Free Software Foundation, Inc.
+   Copyright 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
 
 This file is part of BFD, the Binary File Descriptor library.
 
@@ -298,14 +298,7 @@ elf_merge_symbol (abfd, info, name, sym, psec, pvalue, sym_hash,
   bfd *oldbfd;
   boolean newdyn, olddyn, olddef, newdef, newdyncommon, olddyncommon;
 
-  /* This code is for coping with dynamic objects, and is only useful
-     if we are doing an ELF link.  */
-  if (info->hash->creator != abfd->xvec)
-    return true;
-
   *override = false;
-  *type_change_ok = false;
-  *size_change_ok = false;
 
   sec = *psec;
   bind = ELF_ST_BIND (sym->st_info);
@@ -319,6 +312,17 @@ elf_merge_symbol (abfd, info, name, sym, psec, pvalue, sym_hash,
     return false;
   *sym_hash = h;
 
+  /* This code is for coping with dynamic objects, and is only useful
+     if we are doing an ELF link.  */
+  if (info->hash->creator != abfd->xvec)
+    return true;
+
+  /* For merging, we only care about real symbols.  */
+
+  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 we just created the symbol, mark it as being an ELF symbol.
      Other than that, there is nothing to do--there is no merge issue
      with a newly defined symbol--so we just return.  */
@@ -329,12 +333,6 @@ elf_merge_symbol (abfd, info, name, sym, psec, pvalue, sym_hash,
       return true;
     }
 
-  /* For merging, we only care about real symbols.  */
-
-  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;
-
   /* OLDBFD is a BFD associated with the existing symbol.  */
 
   switch (h->root.type)
@@ -573,7 +571,8 @@ elf_merge_symbol (abfd, info, name, sym, psec, pvalue, sym_hash,
          we want the caller to frob with H rather than with the
          indirect symbol.  That will permit the caller to redefine the
          target of the indirection, rather than the indirect symbol
-         itself.  */
+         itself.  FIXME: This will break the -y option if we store a
+         symbol with a different name.  */
       *sym_hash = h;
     }
 
@@ -1097,7 +1096,7 @@ elf_link_add_object_symbols (abfd, info)
       if (info->hash->creator->flavour == bfd_target_elf_flavour)
        {
          Elf_Internal_Versym iver;
-         int vernum;
+         unsigned int vernum = 0;
          boolean override;
 
          if (ever != NULL)
@@ -1122,7 +1121,7 @@ elf_link_add_object_symbols (abfd, info)
                      if (vernum > elf_tdata (abfd)->dynverdef_hdr.sh_info)
                        {
                          (*_bfd_error_handler)
-                           ("%s: %s: invalid version %d (max %d)",
+                           (_("%s: %s: invalid version %u (max %d)"),
                             abfd->filename, name, vernum,
                             elf_tdata (abfd)->dynverdef_hdr.sh_info);
                          bfd_set_error (bfd_error_bad_value);
@@ -1163,7 +1162,7 @@ elf_link_add_object_symbols (abfd, info)
                      if (verstr == NULL)
                        {
                          (*_bfd_error_handler)
-                           ("%s: %s: invalid needed version %d",
+                           (_("%s: %s: invalid needed version %d"),
                             abfd->filename, name, vernum);
                          bfd_set_error (bfd_error_bad_value);
                          goto error_return;
@@ -1210,10 +1209,10 @@ elf_link_add_object_symbols (abfd, info)
          if (h->root.type == bfd_link_hash_common)
            old_alignment = h->root.u.c.p->alignment_power;
 
-         if (ever != NULL
+         if (elf_tdata (abfd)->verdef != NULL
              && ! override
              && vernum > 1
-             && (h->verinfo.verdef == NULL || definition))
+             && definition)
            h->verinfo.verdef = &elf_tdata (abfd)->verdef[vernum - 1];
        }
 
@@ -1276,7 +1275,7 @@ elf_link_add_object_symbols (abfd, info)
            {
              if (h->size != 0 && h->size != sym.st_size && ! size_change_ok)
                (*_bfd_error_handler)
-                 ("Warning: size of symbol `%s' changed from %lu to %lu in %s",
+                 (_("Warning: size of symbol `%s' changed from %lu to %lu in %s"),
                   name, (unsigned long) h->size, (unsigned long) sym.st_size,
                   bfd_get_filename (abfd));
 
@@ -1298,7 +1297,7 @@ elf_link_add_object_symbols (abfd, info)
                  && h->type != ELF_ST_TYPE (sym.st_info)
                  && ! type_change_ok)
                (*_bfd_error_handler)
-                 ("Warning: type of symbol `%s' changed from %d to %d in %s",
+                 (_("Warning: type of symbol `%s' changed from %d to %d in %s"),
                   name, h->type, ELF_ST_TYPE (sym.st_info),
                   bfd_get_filename (abfd));
 
@@ -1371,6 +1370,8 @@ elf_link_add_object_symbols (abfd, info)
                      purposes of the merge, act as though we were
                      defining the symbol we just defined, although we
                      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, &hi, &override,
                                          &type_change_ok, &size_change_ok))
@@ -1410,6 +1411,10 @@ elf_link_add_object_symbols (abfd, info)
                         mapped to the definition in the regular
                         object.  */
 
+                     while (hi->root.type == bfd_link_hash_indirect
+                            || hi->root.type == bfd_link_hash_warning)
+                       hi = (struct elf_link_hash_entry *) hi->root.u.i.link;
+
                      h->root.type = bfd_link_hash_indirect;
                      h->root.u.i.link = (struct bfd_link_hash_entry *) hi;
                      if (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC)
@@ -1505,6 +1510,8 @@ elf_link_add_object_symbols (abfd, info)
                  strcpy (shortname + (p - name), p + 1);
 
                  /* 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, &hi, &override,
                                          &type_change_ok, &size_change_ok))
@@ -1516,7 +1523,7 @@ elf_link_add_object_symbols (abfd, info)
                          don't expect to see the type of override we
                          do in the case above.  */
                      (*_bfd_error_handler)
-                       ("%s: warning: unexpected redefinition of `%s'",
+                       (_("%s: warning: unexpected redefinition of `%s'"),
                         bfd_get_filename (abfd), shortname);
                    }
                  else
@@ -1839,7 +1846,7 @@ elf_link_create_dynamic_sections (abfd, info)
   s = bfd_make_section (abfd, ".gnu.version_d");
   if (s == NULL
       || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
-      || ! bfd_set_section_alignment (abfd, s, 2))
+      || ! bfd_set_section_alignment (abfd, s, LOG_FILE_ALIGN))
     return false;
 
   s = bfd_make_section (abfd, ".gnu.version");
@@ -1851,7 +1858,7 @@ elf_link_create_dynamic_sections (abfd, info)
   s = bfd_make_section (abfd, ".gnu.version_r");
   if (s == NULL
       || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
-      || ! bfd_set_section_alignment (abfd, s, 2))
+      || ! bfd_set_section_alignment (abfd, s, LOG_FILE_ALIGN))
     return false;
 
   s = bfd_make_section (abfd, ".dynsym");
@@ -2098,6 +2105,15 @@ NAME(bfd_elf,record_link_assignment) (output_bfd, info, name, provide)
       && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
     h->root.type = bfd_link_hash_undefined;
 
+  /* If this symbol is not being provided by the linker script, and it is
+     currently defined by a dynamic object, but not by a regular object,
+     then clear out any version information because the symbol will not be
+     associated with the dynamic object any more.  */
+  if (!provide
+      && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
+      && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+    h->verinfo.verdef = NULL;
+
   h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
   h->type = STT_OBJECT;
 
@@ -2197,7 +2213,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
 
   *sinterpptr = NULL;
 
-  soname_indx = -1;
+  soname_indx = (bfd_size_type) -1;
 
   if (info->hash->creator->flavour != bfd_target_elf_flavour)
     return true;
@@ -2444,7 +2460,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
          def.vd_next = (sizeof (Elf_External_Verdef)
                         + sizeof (Elf_External_Verdaux));
 
-         if (soname_indx != -1)
+         if (soname_indx != (bfd_size_type) -1)
            {
              def.vd_hash = bfd_elf_hash ((const unsigned char *) soname);
              defaux.vda_name = soname_indx;
@@ -2528,7 +2544,14 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
 
              for (n = t->deps; n != NULL; n = n->next)
                {
-                 defaux.vda_name = n->version_needed->name_indx;
+                 if (n->version_needed == NULL)
+                   {
+                     /* This can happen if there was an error in the
+                        version script.  */
+                     defaux.vda_name = 0;
+                   }
+                 else
+                   defaux.vda_name = n->version_needed->name_indx;
                  if (n->next == NULL)
                    defaux.vda_next = 0;
                  else
@@ -3094,26 +3117,37 @@ elf_link_assign_sym_version (h, data)
        {
          if (strcmp (t->name, p) == 0)
            {
+             int len;
+             char *alc;
+             struct bfd_elf_version_expr *d;
+
+             len = p - h->root.root.string;
+             alc = bfd_alloc (sinfo->output_bfd, len);
+             if (alc == NULL)
+               return false;
+             strncpy (alc, h->root.root.string, len - 1);
+             alc[len - 1] = '\0';
+             if (alc[len - 2] == ELF_VER_CHR)
+               alc[len - 2] = '\0';
+
              h->verinfo.vertree = t;
              t->used = true;
+             d = NULL;
+
+             if (t->globals != NULL)
+               {
+                 for (d = t->globals; d != NULL; d = d->next)
+                   {
+                     if ((d->match[0] == '*' && d->match[1] == '\0')
+                         || fnmatch (d->match, alc, 0) == 0)
+                       break;
+                   }
+               }
 
              /* See if there is anything to force this symbol to
                  local scope.  */
-             if (t->locals != NULL)
+             if (d == NULL && t->locals != NULL)
                {
-                 int len;
-                 char *alc;
-                 struct bfd_elf_version_expr *d;
-
-                 len = p - h->root.root.string;
-                 alc = bfd_alloc (sinfo->output_bfd, len);
-                 if (alc == NULL)
-                   return false;
-                 strncpy (alc, h->root.root.string, len - 1);
-                 alc[len - 1] = '\0';
-                 if (alc[len - 2] == ELF_VER_CHR)
-                   alc[len - 2] = '\0';
-
                  for (d = t->locals; d != NULL; d = d->next)
                    {
                      if ((d->match[0] == '*' && d->match[1] == '\0')
@@ -3136,10 +3170,9 @@ elf_link_assign_sym_version (h, data)
                          break;
                        }
                    }
-
-                 bfd_release (sinfo->output_bfd, alc);
                }
 
+             bfd_release (sinfo->output_bfd, alc);
              break;
            }
        }
@@ -3186,7 +3219,7 @@ elf_link_assign_sym_version (h, data)
          /* We could not find the version for a symbol when
              generating a shared archive.  Return an error.  */
          (*_bfd_error_handler)
-           ("%s: undefined version name %s",
+           (_("%s: undefined versioned symbol name %s"),
             bfd_get_filename (sinfo->output_bfd), h->root.root.string);
          bfd_set_error (bfd_error_bad_value);
          sinfo->failed = true;
@@ -4276,7 +4309,7 @@ elf_link_output_extsym (h, data)
       break;
 
     case bfd_link_hash_common:
-      input_sec = bfd_com_section_ptr;
+      input_sec = h->root.u.c.p->section;
       sym.st_shndx = SHN_COMMON;
       sym.st_value = 1 << h->root.u.c.p->alignment_power;
       break;
@@ -4700,6 +4733,7 @@ elf_link_input_bfd (finfo, input_bfd)
                      || (elf_bad_symtab (input_bfd)
                          && finfo->sections[r_symndx] == NULL))
                    {
+                     struct elf_link_hash_entry *rh;
                      long indx;
 
                      /* This is a reloc against a global symbol.  We
@@ -4710,13 +4744,18 @@ elf_link_input_bfd (finfo, input_bfd)
                         for this symbol.  The symbol index is then
                         set at the end of elf_bfd_final_link.  */
                      indx = r_symndx - extsymoff;
-                     *rel_hash = elf_sym_hashes (input_bfd)[indx];
+                     rh = elf_sym_hashes (input_bfd)[indx];
+                     while (rh->root.type == bfd_link_hash_indirect
+                            || rh->root.type == bfd_link_hash_warning)
+                       rh = (struct elf_link_hash_entry *) rh->root.u.i.link;
 
                      /* Setting the index to -2 tells
                         elf_link_output_extsym that this symbol is
                         used by a reloc.  */
-                     BFD_ASSERT ((*rel_hash)->indx < 0);
-                     (*rel_hash)->indx = -2;
+                     BFD_ASSERT (rh->indx < 0);
+                     rh->indx = -2;
+
+                     *rel_hash = rh;
 
                      continue;
                    }
@@ -5064,7 +5103,7 @@ elf_create_pointer_linker_section (abfd, info, lsect, h, rel)
       /* Allocate a table to hold the local symbols if first time */
       if (!ptr)
        {
-         int num_symbols = elf_tdata (abfd)->symtab_hdr.sh_info;
+         unsigned int num_symbols = elf_tdata (abfd)->symtab_hdr.sh_info;
          register unsigned int i;
 
          ptr = (elf_linker_section_pointers_t **)