* elflink.h (elf_link_add_object_symbols): Use extsymoff when
authorIan Lance Taylor <ian@airs.com>
Thu, 13 Mar 1997 02:41:44 +0000 (02:41 +0000)
committerIan Lance Taylor <ian@airs.com>
Thu, 13 Mar 1997 02:41:44 +0000 (02:41 +0000)
setting ever.  Sanity check the version number.  Sort out copying
flags and other information when adding an indirect symbol.
(NAME(bfd_elf,size_dynamic_sections)): Preserve any dynamic
symbols added by the backend.  Clear the entire contents of the
versym section.
(elf_export_symbol): Ignore indirect symbols.
(elf_link_output_extsym): Accept a section without an owner in an
assert.
* elfcode.h (elf_slurp_symbol_table): Add a sanity check on the
version count.  Correct the allocation of x_versymp.

bfd/ChangeLog
bfd/elfcode.h
bfd/elflink.h

index 295938b14c8929edc9d2102d027fd964c69255c0..7b21291c3a5bc313a476fec309246431fd5f7a42 100644 (file)
@@ -1,3 +1,45 @@
+Wed Mar 12 21:36:05 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * elflink.h (elf_link_add_object_symbols): Use extsymoff when
+       setting ever.  Sanity check the version number.  Sort out copying
+       flags and other information when adding an indirect symbol.
+       (NAME(bfd_elf,size_dynamic_sections)): Preserve any dynamic
+       symbols added by the backend.  Clear the entire contents of the
+       versym section.
+       (elf_export_symbol): Ignore indirect symbols.
+       (elf_link_output_extsym): Accept a section without an owner in an
+       assert.
+       * elfcode.h (elf_slurp_symbol_table): Add a sanity check on the
+       version count.  Correct the allocation of x_versymp.
+
+       * elf32-mips.c (mips_elf_add_symbol_hook): Don't set the owner of
+       the magic sections used for SHN_MIPS_TEXT and SHN_MIPS_DATA.
+       Don't return bfd_und_section_ptr when info->shared.
+       (mips_elf_final_link): Set the alignment of .rtproc to 4, not 12.
+       (mips_elf_create_dynamic_sections): Correct type: ^= for &=.
+       (mips_elf_check_relocs): Resolve an indirect symbol in
+       sym_hashes.
+       (mips_elf_finish_dynamic_symbol): Don't change SHN_ABS into
+       SHN_MIPS_TEXT or SHN_MIPS_DATA.
+
+       * elf.c (bfd_elf_print_symbol): Tweak version output slightly.
+
+Tue Mar 11 01:38:36 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       From Eric Youngdale <eric@andante.jic.com>:
+       * elf-bfd.h (ELF_LINK_FORCED_LOCAL): Define.
+       * elf.c (bfd_elf_print_symbol): Correct errors in last change.
+       * elflink.h (elf_link_add_object_symbols): Handle cases in which a
+       versioned symbol appears in both a regular and a shared object.
+       (elf_link_assign_sym_version): Set ELF_LINK_FORCED_LOCAL when
+       appropriate.  Improve error message.
+       (struct elf_outext_info): Rename from elf_finfo_failed.  Change
+       all uses.  Add localsyms field.
+       (elf_bfd_final_link): When generating a shared library, call
+       elf_link_output_extsym to output all local symbols.
+       (elf_link_output_extsym): Handle symbols which were forced to
+       become local.
+
 Sun Mar  9 23:08:49 1997  Ian Lance Taylor  <ian@cygnus.com>
 
        From Eric Youngdale <eric@andante.jic.com>:
index 87e02f2523604e61e8d3ed29f97f9a0451f4de7e..132060157eee02749e8543eeed7bc88d3117892e 100644 (file)
@@ -1,5 +1,5 @@
 /* ELF executable support for BFD.
-   Copyright 1991, 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+   Copyright 1991, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
 
    Written by Fred Fish @ Cygnus Support, from information published
    in "UNIX System V Release 4, Programmers Guide: ANSI C and
@@ -68,6 +68,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "bfdlink.h"
 #include "libbfd.h"
 #include "elf-bfd.h"
+#include "fnmatch.h"
 
 /* Renaming structures, typedefs, macros and functions to be size-specific.  */
 #define Elf_External_Ehdr      NAME(Elf,External_Ehdr)
@@ -455,6 +456,7 @@ elf_object_p (abfd)
   struct elf_backend_data *ebd;
   struct elf_obj_tdata *preserved_tdata = elf_tdata (abfd);
   struct elf_obj_tdata *new_tdata = NULL;
+  asection *s;
 
   /* Read in the ELF header in external format.  */
 
@@ -658,6 +660,25 @@ elf_object_p (abfd)
        goto got_wrong_format_error;
     }
 
+  /* If we have created any reloc sections that are associated with
+     debugging sections, mark the reloc sections as debugging as well.  */
+  for (s = abfd->sections; s != NULL; s = s->next)
+    {
+      if ((elf_section_data (s)->this_hdr.sh_type == SHT_REL
+          || elf_section_data (s)->this_hdr.sh_type == SHT_RELA)
+         && elf_section_data (s)->this_hdr.sh_info > 0)
+       {
+         unsigned long targ_index;
+         asection *targ_sec;
+
+         targ_index = elf_section_data (s)->this_hdr.sh_info;
+         targ_sec = bfd_section_from_elf_index (abfd, targ_index);
+         if (targ_sec != NULL
+             && (targ_sec->flags & SEC_DEBUGGING) != 0)
+           s->flags |= SEC_DEBUGGING;
+       }
+    }
+
   return (abfd->xvec);
 
 got_wrong_format_error:
@@ -902,11 +923,13 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic)
      boolean dynamic;
 {
   Elf_Internal_Shdr *hdr;
+  Elf_Internal_Shdr *verhdr;
   long symcount;               /* Number of external ELF symbols */
   elf_symbol_type *sym;                /* Pointer to current bfd symbol */
   elf_symbol_type *symbase;    /* Buffer for generated bfd symbols */
   Elf_Internal_Sym i_sym;
   Elf_External_Sym *x_symp = NULL;
+  Elf_External_Versym *x_versymp = NULL;
 
   /* Read each raw ELF symbol, converting from external ELF form to
      internal ELF form, and then using the information to create a
@@ -918,10 +941,25 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic)
      space left over at the end.  When we have all the symbols, we
      build the caller's pointer vector. */
 
-  if (dynamic)
-    hdr = &elf_tdata (abfd)->dynsymtab_hdr;
+  if (! dynamic)
+    {
+      hdr = &elf_tdata (abfd)->symtab_hdr;
+      verhdr = NULL;
+    }
   else
-    hdr = &elf_tdata (abfd)->symtab_hdr;
+    {
+      hdr = &elf_tdata (abfd)->dynsymtab_hdr;
+      verhdr = &elf_tdata (abfd)->dynversym_hdr;
+      if ((elf_tdata (abfd)->dynverdef_section != 0
+          && elf_tdata (abfd)->verdef == NULL)
+         || (elf_tdata (abfd)->dynverref_section != 0
+             && elf_tdata (abfd)->verref == NULL))
+       {
+         if (! _bfd_elf_slurp_version_tables (abfd))
+           return -1;
+       }
+    }
+
   if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) == -1)
     return -1;
 
@@ -951,6 +989,38 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic)
       if (bfd_read ((PTR) x_symp, sizeof (Elf_External_Sym), symcount, abfd)
          != symcount * sizeof (Elf_External_Sym))
        goto error_return;
+
+      /* Read the raw ELF version symbol information.  */
+
+      if (elf_dynversym (abfd) != 0
+         && verhdr != NULL
+         && verhdr->sh_size / sizeof (Elf_External_Versym) != symcount)
+       {
+         (*_bfd_error_handler)
+           ("%s: version count (%ld) does not match symbol count (%ld)",
+            abfd->filename,
+            (long) (verhdr->sh_size / sizeof (Elf_External_Versym)),
+            symcount);
+
+         /* Slurp in the symbols without the version information,
+             since that is more helpful than just quitting.  */
+         verhdr = NULL;
+       }
+
+      if (verhdr != NULL)
+       {
+         if (bfd_seek (abfd, verhdr->sh_offset, SEEK_SET) != 0)
+           goto error_return;
+
+         x_versymp = (Elf_External_Versym *) bfd_malloc (verhdr->sh_size);
+         if (x_versymp == NULL && symcount != 0)
+           goto error_return;
+
+         if (bfd_read ((PTR) x_versymp, 1, verhdr->sh_size, abfd)
+             != verhdr->sh_size)
+           goto error_return;
+       }
+
       /* Skip first symbol, which is a null dummy.  */
       for (i = 1; i < symcount; i++)
        {
@@ -1035,6 +1105,14 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic)
          if (dynamic)
            sym->symbol.flags |= BSF_DYNAMIC;
 
+         if (x_versymp != NULL)
+           {
+             Elf_Internal_Versym iversym;
+
+             _bfd_elf_swap_versym_in (abfd, x_versymp + i, &iversym);
+             sym->version = iversym.vs_vers;
+           }
+
          /* Do some backend-specific processing on this symbol.  */
          {
            struct elf_backend_data *ebd = get_elf_backend_data (abfd);
@@ -1071,10 +1149,14 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic)
       *symptrs = 0;            /* Final null pointer */
     }
 
+  if (x_versymp != NULL)
+    free (x_versymp);
   if (x_symp != NULL)
     free (x_symp);
   return symcount;
 error_return:
+  if (x_versymp != NULL)
+    free (x_versymp);
   if (x_symp != NULL)
     free (x_symp);
   return -1;
index 28df37e108b75a78c7c6b9b0bbcef4cd043d4ce2..b6a5d580a30460d0816137eaf6567c9f5db3aecd 100644 (file)
@@ -679,7 +679,7 @@ elf_link_add_object_symbols (abfd, info)
 
   weaks = NULL;
 
-  ever = extversym != NULL ? extversym + hdr->sh_info : NULL;
+  ever = extversym != NULL ? extversym + extsymoff : NULL;
   esymend = buf + extsymcount;
   for (esym = buf;
        esym < esymend;
@@ -805,7 +805,16 @@ elf_link_add_object_symbols (abfd, info)
                  int namelen, newlen;
                  char *newname, *p;
 
-                 if (vernum > 1)
+                 if (vernum > elf_tdata (abfd)->dynverdef_hdr.sh_info)
+                   {
+                     (*_bfd_error_handler)
+                       ("%s: %s: invalid version %d (max %d)",
+                        abfd->filename, name, vernum,
+                        elf_tdata (abfd)->dynverdef_hdr.sh_info);
+                     bfd_set_error (bfd_error_bad_value);
+                     goto error_return;
+                   }
+                 else if (vernum > 1)
                    verstr = elf_tdata (abfd)->verdef[vernum - 1].vd_nodename;
                  else
                    verstr = "";
@@ -1128,15 +1137,64 @@ elf_link_add_object_symbols (abfd, info)
                      if (hi->root.type == bfd_link_hash_indirect)
                        {
                          hi->elf_link_hash_flags &= ~ ELF_LINK_NON_ELF;
-                         if (dynamic)
-                           hi->elf_link_hash_flags |=
-                             ELF_LINK_HASH_DEF_DYNAMIC;
-                         /* We don't set DEF_REGULAR because we don't
-                            the symbol to get exported even if we are
-                            exporting all defined symbols.  FIXME:
-                            What a hack. */
-                         /* FIXME: Do we need to copy any flags from
-                            H to HI?  */
+
+                         /* If the symbol became indirect, then we
+                             assume that we have not seen a definition
+                             before.  */
+                         BFD_ASSERT ((hi->elf_link_hash_flags
+                                      & (ELF_LINK_HASH_DEF_DYNAMIC
+                                         | ELF_LINK_HASH_DEF_REGULAR))
+                                     == 0);
+
+                         /* Copy down any references that we may have
+                             already seen to the symbol which just
+                             became indirect.  */
+                         h->elf_link_hash_flags |=
+                           (hi->elf_link_hash_flags
+                            & (ELF_LINK_HASH_REF_DYNAMIC
+                               | ELF_LINK_HASH_REF_REGULAR));
+
+                         /* Copy over the global table offset entry.
+                             This may have been already set up by a
+                             check_relocs routine.  */
+                         if (h->got_offset == (bfd_vma) -1)
+                           {
+                             h->got_offset = hi->got_offset;
+                             hi->got_offset = (bfd_vma) -1;
+                           }
+                         BFD_ASSERT (hi->got_offset == (bfd_vma) -1);
+
+                         if (h->dynindx == -1)
+                           {
+                             h->dynindx = hi->dynindx;
+                             h->dynstr_index = hi->dynstr_index;
+                             hi->dynindx = -1;
+                             hi->dynstr_index = 0;
+                           }
+                         BFD_ASSERT (hi->dynindx == -1);
+
+                         /* FIXME: There may be other information to
+                             copy over for particular targets.  */
+
+                         /* See if the new flags lead us to realize
+                             that the symbol must be dynamic.  */
+                         if (! dynsym)
+                           {
+                             if (! dynamic)
+                               {
+                                 if (info->shared
+                                     || ((hi->elf_link_hash_flags
+                                          & ELF_LINK_HASH_REF_DYNAMIC)
+                                         != 0))
+                                   dynsym = true;
+                               }
+                             else
+                               {
+                                 if ((hi->elf_link_hash_flags
+                                      & ELF_LINK_HASH_REF_REGULAR) != 0)
+                                   dynsym = true;
+                               }
+                           }
                        }
                    }
 
@@ -1211,15 +1269,64 @@ elf_link_add_object_symbols (abfd, info)
                      if (hi->root.type == bfd_link_hash_indirect)
                        {
                          hi->elf_link_hash_flags &= ~ ELF_LINK_NON_ELF;
-                         if (dynamic)
-                           hi->elf_link_hash_flags |=
-                             ELF_LINK_HASH_DEF_DYNAMIC;
-                         /* We don't set DEF_REGULAR because we don't
-                            the symbol to get exported even if we are
-                            exporting all defined symbols.  FIXME:
-                            What a hack. */
-                         /* FIXME: Do we need to copy any flags from
-                            H to HI?  */
+
+                         /* If the symbol became indirect, then we
+                             assume that we have not seen a definition
+                             before.  */
+                         BFD_ASSERT ((hi->elf_link_hash_flags
+                                      & (ELF_LINK_HASH_DEF_DYNAMIC
+                                         | ELF_LINK_HASH_DEF_REGULAR))
+                                     == 0);
+
+                         /* Copy down any references that we may have
+                             already seen to the symbol which just
+                             became indirect.  */
+                         h->elf_link_hash_flags |=
+                           (hi->elf_link_hash_flags
+                            & (ELF_LINK_HASH_REF_DYNAMIC
+                               | ELF_LINK_HASH_REF_REGULAR));
+
+                         /* Copy over the global table offset entry.
+                             This may have been already set up by a
+                             check_relocs routine.  */
+                         if (h->got_offset == (bfd_vma) -1)
+                           {
+                             h->got_offset = hi->got_offset;
+                             hi->got_offset = (bfd_vma) -1;
+                           }
+                         BFD_ASSERT (hi->got_offset == (bfd_vma) -1);
+
+                         if (h->dynindx == -1)
+                           {
+                             h->dynindx = hi->dynindx;
+                             h->dynstr_index = hi->dynstr_index;
+                             hi->dynindx = -1;
+                             hi->dynstr_index = 0;
+                           }
+                         BFD_ASSERT (hi->dynindx == -1);
+
+                         /* FIXME: There may be other information to
+                             copy over for particular targets.  */
+
+                         /* See if the new flags lead us to realize
+                             that the symbol must be dynamic.  */
+                         if (! dynsym)
+                           {
+                             if (! dynamic)
+                               {
+                                 if (info->shared
+                                     || ((hi->elf_link_hash_flags
+                                          & ELF_LINK_HASH_REF_DYNAMIC)
+                                         != 0))
+                                   dynsym = true;
+                               }
+                             else
+                               {
+                                 if ((hi->elf_link_hash_flags
+                                      & ELF_LINK_HASH_REF_REGULAR) != 0)
+                                   dynsym = true;
+                               }
+                           }
                        }
                    }
                }
@@ -1818,6 +1925,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
   bfd_size_type soname_indx;
   bfd *dynobj;
   struct elf_backend_data *bed;
+  bfd_size_type old_dynsymcount;
 
   *sinterpptr = NULL;
 
@@ -1959,6 +2067,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
 
   /* The backend must work out the sizes of all the other dynamic
      sections.  */
+  old_dynsymcount = elf_hash_table (info)->dynsymcount;
   if (! (*bed->elf_backend_size_dynamic_sections) (output_bfd, info))
     return false;
 
@@ -2018,11 +2127,15 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
          if (sinfo.removed_dynamic)
            {
              /* Some dynamic symbols were changed to be local
-                 symbols.  In this case, we renumber all of the
-                 dynamic symbols, so that we don't have a hole.
-                 FIXME: The names of the removed symbols will still be
-                 in the dynamic string table, wasting space.  */
-             elf_hash_table (info)->dynsymcount = 1;
+                symbols.  In this case, we renumber all of the
+                dynamic symbols, so that we don't have a hole.  If
+                the backend changed dynsymcount, then assume that the
+                new symbols are at the start.  This is the case on
+                the MIPS.  FIXME: The names of the removed symbols
+                will still be in the dynamic string table, wasting
+                space.  */
+             elf_hash_table (info)->dynsymcount =
+               1 + (elf_hash_table (info)->dynsymcount - old_dynsymcount);
              elf_link_hash_traverse (elf_hash_table (info),
                                      elf_link_renumber_dynsyms,
                                      (PTR) info);
@@ -2307,17 +2420,11 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
        }
       else
        {
-         Elf_Internal_Versym intversym;
-
          s->_raw_size = dynsymcount * sizeof (Elf_External_Versym);
-         s->contents = (bfd_byte *) bfd_alloc (output_bfd, s->_raw_size);
+         s->contents = (bfd_byte *) bfd_zalloc (output_bfd, s->_raw_size);
          if (s->contents == NULL)
            return false;
 
-         intversym.vs_vers = 0;
-         _bfd_elf_swap_versym_out (output_bfd, &intversym,
-                                   (Elf_External_Versym *) s->contents);
-
          if (! elf_add_dynamic_entry (info, DT_VERSYM, 0))
            return false;
        }
@@ -2389,7 +2496,7 @@ elf_adjust_dynamic_symbol (h, data)
   bfd *dynobj;
   struct elf_backend_data *bed;
 
-  /* Ignore indirect symbols.  There are added by the versioning code.  */
+  /* Ignore indirect symbols.  These are added by the versioning code.  */
   if (h->root.type == bfd_link_hash_indirect)
     return true;
 
@@ -2546,6 +2653,10 @@ elf_export_symbol (h, data)
 {
   struct elf_info_failed *eif = (struct elf_info_failed *) data;
 
+  /* Ignore indirect symbols.  These are added by the versioning code.  */
+  if (h->root.type == bfd_link_hash_indirect)
+    return true;
+
   if (h->dynindx == -1
       && (h->elf_link_hash_flags
          & (ELF_LINK_HASH_DEF_REGULAR | ELF_LINK_HASH_REF_REGULAR)) != 0)
@@ -3853,7 +3964,8 @@ elf_link_output_extsym (h, data)
          }
        else
          {
-           BFD_ASSERT ((input_sec->owner->flags & DYNAMIC) != 0);
+           BFD_ASSERT (input_sec->owner == NULL
+                       || (input_sec->owner->flags & DYNAMIC) != 0);
            sym.st_shndx = SHN_UNDEF;
            input_sec = bfd_und_section_ptr;
          }