OSDN Git Service

* elf-bfd.h (struct elf_link_local_dynamic_entry): New.
authorRichard Henderson <rth@redhat.com>
Tue, 13 Jul 1999 18:21:29 +0000 (18:21 +0000)
committerRichard Henderson <rth@redhat.com>
Tue, 13 Jul 1999 18:21:29 +0000 (18:21 +0000)
(struct elf_link_hash_table): Add dynlocal.
(_bfd_elf_link_lookup_local_dynindx): Prototype.
(_bfd_elf_link_adjust_dynindx): Delete.
(_bfd_elf_link_renumber_dynsyms): Prototype.
(_bfd_elf,link_record_local_dynamic_symbol): Prototype.
* elfcode.h (elf_link_record_local_dynamic_symbol): New alias.
* elflink.c (_bfd_elf_link_adjust_dynindx): Delete.
(_bfd_elf_link_lookup_local_dynindx): New function.
(elf_link_renumber_hash_table_dynsyms): New function.
(_bfd_elf_link_renumber_dynsyms): New function.
* elflink.h (elf_link_record_local_dynamic_symbol): New function.
(struct elf_assign_sym_version_info): Delete removed_dynamic.
(bfd_elf,size_dynamic_sections): Use _bfd_strip_section_from_output
instead of elf_link_remove_section_and_adjust_dynindices.
Remove removed_dynamic code.  Use _bfd_elf_link_renumber_dynsyms.
(elf_link_assign_sym_version): Remove removed_dynamic code.
(elf_link_renumber_dynsyms): Delete.
(elf_bfd_final_link): Install section and local symbols into .dynsym.
* elf32-m68k.c (elf_m68k_adjust_dynindx): Delete.
(elf_m68k_size_dynamic_sections): Don't set section dynindicies.
(elf_m68k_finish_dynamic_sections): Don't write section dynsyms.
* elf32-mips.c: Similarly.
* elf32-ppc.c: Similarly.
* elf32-sparc.c: Similarly.
* elf64-alpha.c: Similarly.
* elf64-sparc.c: Similarly.

bfd/ChangeLog
bfd/elf-bfd.h
bfd/elf32-m68k.c
bfd/elf32-mips.c
bfd/elf32-ppc.c
bfd/elf32-sparc.c
bfd/elf64-alpha.c
bfd/elf64-sparc.c
bfd/elfcode.h
bfd/elflink.c
bfd/elflink.h

index 78787ad..e3d3275 100644 (file)
@@ -1,3 +1,36 @@
+1999-07-13  Richard Henderson  <rth@cygnus.com>
+
+       * elf.c (assign_file_positions_for_segments): Don't overwrite p_flags.
+
+       * elf-bfd.h (struct elf_link_local_dynamic_entry): New.
+       (struct elf_link_hash_table): Add dynlocal.
+       (_bfd_elf_link_lookup_local_dynindx): Prototype.
+       (_bfd_elf_link_adjust_dynindx): Delete.
+       (_bfd_elf_link_renumber_dynsyms): Prototype.
+       (_bfd_elf,link_record_local_dynamic_symbol): Prototype.
+       * elfcode.h (elf_link_record_local_dynamic_symbol): New alias.
+       * elflink.c (_bfd_elf_link_adjust_dynindx): Delete.
+       (_bfd_elf_link_lookup_local_dynindx): New function.
+       (elf_link_renumber_hash_table_dynsyms): New function.
+       (_bfd_elf_link_renumber_dynsyms): New function.
+       * elflink.h (elf_link_record_local_dynamic_symbol): New function.
+       (struct elf_assign_sym_version_info): Delete removed_dynamic.
+       (bfd_elf,size_dynamic_sections): Use _bfd_strip_section_from_output
+       instead of elf_link_remove_section_and_adjust_dynindices.
+       Remove removed_dynamic code.  Use _bfd_elf_link_renumber_dynsyms.
+       (elf_link_assign_sym_version): Remove removed_dynamic code.
+       (elf_link_renumber_dynsyms): Delete.
+       (elf_bfd_final_link): Install section and local symbols into .dynsym.
+
+       * elf32-m68k.c (elf_m68k_adjust_dynindx): Delete.
+       (elf_m68k_size_dynamic_sections): Don't set section dynindicies.
+       (elf_m68k_finish_dynamic_sections): Don't write section dynsyms.
+       * elf32-mips.c: Similarly.
+       * elf32-ppc.c: Similarly.
+       * elf32-sparc.c: Similarly.
+       * elf64-alpha.c: Similarly.
+       * elf64-sparc.c: Similarly.
+
 1999-07-13  Mark Mitchell  <mark@codesourcery.com>
 
        * elf32-mips.c (mips_elf_calculate_relocation): Do not complain
index be6185b..6c20b06 100644 (file)
@@ -86,6 +86,16 @@ struct elf_link_hash_entry
 
   /* Symbol index as a dynamic symbol.  Initialized to -1, and remains
      -1 if this is not a dynamic symbol.  */
+  /* ??? Note that this is consistently used as a synonym for tests
+     against whether we can perform various simplifying transformations
+     to the code.  (E.g. changing a pc-relative jump to a PLT entry
+     into a pc-relative jump to the target function.)  That test, which
+     is often relatively complex, and someplaces wrong or incomplete,
+     should really be replaced by a predicate in elflink.c.
+
+     End result: this field -1 does not indicate that the symbol is
+     not in the dynamic symbol table, but rather that the symbol is
+     not visible outside this DSO.  */
   long dynindx;
 
   /* String table index in .dynstr if this is a dynamic symbol.  */
@@ -181,6 +191,25 @@ struct elf_link_hash_entry
 #define ELF_LINK_HASH_MARK 04000
 };
 
+/* Records local symbols to be emitted in the dynamic symbol table.  */
+
+struct elf_link_local_dynamic_entry
+{
+  struct elf_link_local_dynamic_entry *next;
+
+  /* The input bfd this symbol came from.  */
+  bfd *input_bfd;
+
+  /* The index of the local symbol being copied.  */
+  long input_indx;
+
+  /* The index in the outgoing dynamic symbol table.  */
+  long dynindx;
+  
+  /* A copy of the input symbol.  */
+  Elf_Internal_Sym isym;
+};
+
 /* ELF linker hash table.  */
 
 struct elf_link_hash_table
@@ -209,6 +238,8 @@ struct elf_link_hash_table
   struct elf_link_hash_entry *hgot;
   /* A pointer to information used to link stabs in sections.  */
   PTR stab_info;
+  /* A linked list of local symbols to be added to .dynsym.  */
+  struct elf_link_local_dynamic_entry *dynlocal;
 };
 
 /* Look up an entry in an ELF linker hash table.  */
@@ -956,6 +987,9 @@ struct bfd_strtab_hash *_bfd_elf_stringtab_init PARAMS ((void));
 boolean
 _bfd_elf_link_record_dynamic_symbol PARAMS ((struct bfd_link_info *,
                                             struct elf_link_hash_entry *));
+long
+_bfd_elf_link_lookup_local_dynindx PARAMS ((struct bfd_link_info *,
+                                           bfd *, long));
 boolean
 _bfd_elf_compute_section_file_positions PARAMS ((bfd *,
                                                 struct bfd_link_info *));
@@ -970,8 +1004,8 @@ boolean _bfd_elf_create_dynamic_sections PARAMS ((bfd *,
                                                  struct bfd_link_info *));
 boolean _bfd_elf_create_got_section PARAMS ((bfd *,
                                             struct bfd_link_info *));
-boolean _bfd_elf_link_adjust_dynindx PARAMS ((struct elf_link_hash_entry *,
-                                             PTR));
+unsigned long _bfd_elf_link_renumber_dynsyms PARAMS ((bfd *,
+                                                     struct bfd_link_info *));
 
 elf_linker_section_t *_bfd_elf_create_linker_section
   PARAMS ((bfd *abfd,
@@ -1113,8 +1147,15 @@ extern boolean bfd_elf64_link_create_dynamic_sections
 extern Elf_Internal_Rela *_bfd_elf64_link_read_relocs
   PARAMS ((bfd *, asection *, PTR, Elf_Internal_Rela *, boolean));
 
-#define bfd_elf32_link_record_dynamic_symbol _bfd_elf_link_record_dynamic_symbol
-#define bfd_elf64_link_record_dynamic_symbol _bfd_elf_link_record_dynamic_symbol
+#define bfd_elf32_link_record_dynamic_symbol \
+  _bfd_elf_link_record_dynamic_symbol
+#define bfd_elf64_link_record_dynamic_symbol \
+  _bfd_elf_link_record_dynamic_symbol
+
+boolean _bfd_elf32_link_record_local_dynamic_symbol
+  PARAMS ((struct bfd_link_info *, bfd *, long));
+boolean _bfd_elf64_link_record_local_dynamic_symbol
+  PARAMS ((struct bfd_link_info *, bfd *, long));
 
 extern boolean _bfd_elf_close_and_cleanup PARAMS ((bfd *));
 extern bfd_reloc_status_type _bfd_elf_rel_vtable_reloc_fn
index 36f6279..709057b 100644 (file)
@@ -43,8 +43,6 @@ static boolean elf_m68k_gc_sweep_hook
           const Elf_Internal_Rela *));
 static boolean elf_m68k_adjust_dynamic_symbol
   PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
-static boolean elf_m68k_adjust_dynindx
-  PARAMS ((struct elf_link_hash_entry *, PTR));
 static boolean elf_m68k_size_dynamic_sections
   PARAMS ((bfd *, struct bfd_link_info *));
 static boolean elf_m68k_relocate_section
@@ -1312,51 +1310,6 @@ elf_m68k_size_dynamic_sections (output_bfd, info)
        }
     }
 
-  /* If we are generating a shared library, we generate a section
-     symbol for each output section for which we might need to copy
-     relocs.  These are local symbols, which means that they must come
-     first in the dynamic symbol table.  That means we must increment
-     the dynamic symbol index of every other dynamic symbol.  */
-  if (info->shared)
-    {
-      int c;
-
-      c = 0;
-      for (s = output_bfd->sections; s != NULL; s = s->next)
-       {
-         if ((s->flags & SEC_LINKER_CREATED) != 0
-             || (s->flags & SEC_ALLOC) == 0)
-           continue;
-
-         elf_section_data (s)->dynindx = c + 1;
-
-         /* These symbols will have no names, so we don't need to
-             fiddle with dynstr_index.  */
-
-         ++c;
-       }
-
-      elf_link_hash_traverse (elf_hash_table (info),
-                             elf_m68k_adjust_dynindx,
-                             (PTR) &c);
-      elf_hash_table (info)->dynsymcount += c;
-    }
-
-  return true;
-}
-
-/* Increment the index of a dynamic symbol by a given amount.  Called
-   via elf_link_hash_traverse.  */
-
-static boolean
-elf_m68k_adjust_dynindx (h, cparg)
-     struct elf_link_hash_entry *h;
-     PTR cparg;
-{
-  int *cp = (int *) cparg;
-
-  if (h->dynindx != -1)
-    h->dynindx += *cp;
   return true;
 }
 
@@ -2213,50 +2166,6 @@ elf_m68k_finish_dynamic_sections (output_bfd, info)
 
   elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
 
-  if (info->shared)
-    {
-      asection *sdynsym;
-      asection *s;
-      Elf_Internal_Sym sym;
-      int c;
-
-      /* Set up the section symbols for the output sections.  */
-
-      sdynsym = bfd_get_section_by_name (dynobj, ".dynsym");
-      BFD_ASSERT (sdynsym != NULL);
-
-      sym.st_size = 0;
-      sym.st_name = 0;
-      sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
-      sym.st_other = 0;
-
-      c = 0;
-      for (s = output_bfd->sections; s != NULL; s = s->next)
-       {
-         int indx;
-
-         if (elf_section_data (s)->dynindx == 0)
-           continue;
-
-         sym.st_value = s->vma;
-
-         indx = elf_section_data (s)->this_idx;
-         BFD_ASSERT (indx > 0);
-         sym.st_shndx = indx;
-
-         bfd_elf32_swap_symbol_out (output_bfd, &sym,
-                                    (PTR) (((Elf32_External_Sym *)
-                                            sdynsym->contents)
-                                           + elf_section_data (s)->dynindx));
-
-         ++c;
-       }
-
-      /* Set the sh_info field of the output .dynsym section to the
-         index of the first global symbol.  */
-      elf_section_data (sdynsym->output_section)->this_hdr.sh_info = c + 1;
-    }
-
   return true;
 }
 
index 03d7f3f..5f04726 100644 (file)
@@ -7693,32 +7693,6 @@ _bfd_mips_elf_size_dynamic_sections (output_bfd, info)
        return false;
     }
 
-  /* If we use dynamic linking, we generate a section symbol for each
-     output section.  These are local symbols, which means that they
-     must come first in the dynamic symbol table.
-     That means we must increment the dynamic symbol index of every
-     other dynamic symbol.  */
-  {
-    unsigned int c, i;
-
-    c = 0;
-    if (elf_hash_table (info)->dynamic_sections_created)
-      {
-       c = bfd_count_sections (output_bfd);
-       elf_link_hash_traverse (elf_hash_table (info),
-                               _bfd_elf_link_adjust_dynindx,
-                               (PTR) &c);
-       elf_hash_table (info)->dynsymcount += c;
-
-       for (i = 1, s = output_bfd->sections; s != NULL; s = s->next, i++)
-         {
-           elf_section_data (s)->dynindx = i;
-           /* These symbols will have no names, so we don't need to
-              fiddle with dynstr_index.  */
-         }
-      }
-  }
-
   return true;
 }
 
@@ -8163,59 +8137,32 @@ _bfd_mips_elf_finish_dynamic_sections (output_bfd, info)
       = MIPS_ELF_GOT_SIZE (output_bfd);
 
   {
-    asection *sdynsym;
     asection *smsym;
     asection *s;
-    Elf_Internal_Sym sym;
     Elf32_compact_rel cpt;
 
-    /* Set up the section symbols for the output sections. SGI sets
-       the STT_NOTYPE attribute for these symbols.  Should we do so?  */
+    /* ??? The section symbols for the output sections were set up in
+       _bfd_elf_final_link.  SGI sets the STT_NOTYPE attribute for these
+       symbols.  Should we do so?  */
 
-    sdynsym = bfd_get_section_by_name (dynobj, ".dynsym");
     smsym = bfd_get_section_by_name (dynobj, 
                                     MIPS_ELF_MSYM_SECTION_NAME (dynobj));
-    if (sdynsym != NULL)
+    if (smsym != NULL)
       {
        Elf32_Internal_Msym msym;
 
-       sym.st_size = 0;
-       sym.st_name = 0;
-       sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
-       sym.st_other = 0;
-
        msym.ms_hash_value = 0;
        msym.ms_info = ELF32_MS_INFO (0, 1);
 
        for (s = output_bfd->sections; s != NULL; s = s->next)
          {
-           int indx;
-           long dynindx;
-
-           sym.st_value = s->vma;
-
-           indx = elf_section_data (s)->this_idx;
-           BFD_ASSERT (indx > 0);
-           sym.st_shndx = indx;
-               
-           dynindx  = elf_section_data (s)->dynindx;
-
-           (*get_elf_backend_data (output_bfd)->s->swap_symbol_out)
-             (output_bfd, &sym, 
-              sdynsym->contents 
-              + (dynindx * MIPS_ELF_SYM_SIZE (output_bfd)));
-               
-           if (smsym)
-             bfd_mips_elf_swap_msym_out 
-               (output_bfd, &msym,
-                (((Elf32_External_Msym *) smsym->contents)
-                 + dynindx));
-         }
+           long dynindx = elf_section_data (s)->dynindx;
 
-       /* Set the sh_info field of the output .dynsym section to
-              the index of the first global symbol.  */
-       elf_section_data (sdynsym->output_section)->this_hdr.sh_info =
-         bfd_count_sections (output_bfd) + 1;
+           bfd_mips_elf_swap_msym_out 
+             (output_bfd, &msym,
+              (((Elf32_External_Msym *) smsym->contents)
+               + dynindx));
+         }
       }
 
     if (SGI_COMPAT (output_bfd))
index e8d512c..83689c2 100644 (file)
@@ -80,8 +80,6 @@ static boolean ppc_elf_gc_sweep_hook PARAMS ((bfd *abfd,
 static boolean ppc_elf_adjust_dynamic_symbol PARAMS ((struct bfd_link_info *,
                                                      struct elf_link_hash_entry *));
 
-static boolean ppc_elf_adjust_dynindx PARAMS ((struct elf_link_hash_entry *, PTR));
-
 static boolean ppc_elf_size_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *));
 
 static boolean ppc_elf_relocate_section PARAMS ((bfd *,
@@ -1881,27 +1879,6 @@ ppc_elf_adjust_dynamic_symbol (info, h)
 }
 
 \f
-/* Increment the index of a dynamic symbol by a given amount.  Called
-   via elf_link_hash_traverse.  */
-
-static boolean
-ppc_elf_adjust_dynindx (h, cparg)
-     struct elf_link_hash_entry *h;
-     PTR cparg;
-{
-  int *cp = (int *) cparg;
-
-#ifdef DEBUG
-  fprintf (stderr, "ppc_elf_adjust_dynindx called, h->dynindx = %d, *cp = %d\n", h->dynindx, *cp);
-#endif
-
-  if (h->dynindx != -1)
-    h->dynindx += *cp;
-
-  return true;
-}
-
-\f
 /* Set the sizes of the dynamic sections.  */
 
 static boolean
@@ -2083,43 +2060,6 @@ ppc_elf_size_dynamic_sections (output_bfd, info)
        }
     }
 
-  /* If we are generating a shared library, we generate a section
-     symbol for each output section.  These are local symbols, which
-     means that they must come first in the dynamic symbol table.
-     That means we must increment the dynamic symbol index of every
-     other dynamic symbol.
-
-     FIXME: We assume that there will never be relocations to
-     locations in linker-created sections that do not have
-     externally-visible names. Instead, we should work out precisely
-     which sections relocations are targetted at.  */
-  if (info->shared)
-    {
-      int c;
-
-      for (c = 0, s = output_bfd->sections; s != NULL; s = s->next)
-       {
-         if ((s->flags & SEC_LINKER_CREATED) != 0
-             || (s->flags & SEC_ALLOC) == 0)
-           {
-             elf_section_data (s)->dynindx = 0;
-             continue;
-           }
-
-         /* These symbols will have no names, so we don't need to
-            fiddle with dynstr_index.  */
-
-         elf_section_data (s)->dynindx = c + 1;
-
-         c++;
-       }
-
-      elf_link_hash_traverse (elf_hash_table (info),
-                             ppc_elf_adjust_dynindx,
-                             (PTR) &c);
-      elf_hash_table (info)->dynsymcount += c;
-    }
-
   return true;
 }
 
@@ -2924,54 +2864,6 @@ ppc_elf_finish_dynamic_sections (output_bfd, info)
       elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
     }
 
-  if (info->shared)
-    {
-      asection *sdynsym;
-      asection *s;
-      Elf_Internal_Sym sym;
-      int maxdindx = 0;
-
-      /* Set up the section symbols for the output sections.  */
-
-      sdynsym = bfd_get_section_by_name (dynobj, ".dynsym");
-      BFD_ASSERT (sdynsym != NULL);
-
-      sym.st_size = 0;
-      sym.st_name = 0;
-      sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
-      sym.st_other = 0;
-
-      for (s = output_bfd->sections; s != NULL; s = s->next)
-       {
-         int indx, dindx;
-
-         sym.st_value = s->vma;
-
-         indx = elf_section_data (s)->this_idx;
-         dindx = elf_section_data (s)->dynindx;
-         if (dindx > 0)
-           {
-             BFD_ASSERT(indx > 0);
-             BFD_ASSERT(dindx > 0);
-
-             if (dindx > maxdindx)
-               maxdindx = dindx;
-
-             sym.st_shndx = indx;
-
-             bfd_elf32_swap_symbol_out (output_bfd, &sym,
-                                        (PTR) (((Elf32_External_Sym *)
-                                                sdynsym->contents)
-                                               + dindx));
-           }
-       }
-
-      /* Set the sh_info field of the output .dynsym section to the
-         index of the first global symbol.  */
-      elf_section_data (sdynsym->output_section)->this_hdr.sh_info =
-       maxdindx + 1;
-    }
-
   return true;
 }
 
index 9cd1d91..2118c70 100644 (file)
@@ -33,8 +33,6 @@ static boolean elf32_sparc_check_relocs
           const Elf_Internal_Rela *));
 static boolean elf32_sparc_adjust_dynamic_symbol
   PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
-static boolean elf32_sparc_adjust_dynindx
-  PARAMS ((struct elf_link_hash_entry *, PTR));
 static boolean elf32_sparc_size_dynamic_sections
   PARAMS ((bfd *, struct bfd_link_info *));
 static boolean elf32_sparc_relocate_section
@@ -1043,51 +1041,6 @@ elf32_sparc_size_dynamic_sections (output_bfd, info)
        }
     }
 
-  /* If we are generating a shared library, we generate a section
-     symbol for each output section for which we might need to copy
-     relocs.  These are local symbols, which means that they must come
-     first in the dynamic symbol table.  That means we must increment
-     the dynamic symbol index of every other dynamic symbol.  */
-  if (info->shared)
-    {
-      int c;
-
-      c = 0;
-      for (s = output_bfd->sections; s != NULL; s = s->next)
-       {
-         if ((s->flags & SEC_LINKER_CREATED) != 0
-             || (s->flags & SEC_ALLOC) == 0)
-           continue;
-
-         elf_section_data (s)->dynindx = c + 1;
-
-         /* These symbols will have no names, so we don't need to
-             fiddle with dynstr_index.  */
-
-         ++c;
-       }
-
-      elf_link_hash_traverse (elf_hash_table (info),
-                             elf32_sparc_adjust_dynindx,
-                             (PTR) &c);
-      elf_hash_table (info)->dynsymcount += c;
-    }
-
-  return true;
-}
-
-/* Increment the index of a dynamic symbol by a given amount.  Called
-   via elf_link_hash_traverse.  */
-
-static boolean
-elf32_sparc_adjust_dynindx (h, cparg)
-     struct elf_link_hash_entry *h;
-     PTR cparg;
-{
-  int *cp = (int *) cparg;
-
-  if (h->dynindx != -1)
-    h->dynindx += *cp;
   return true;
 }
 
@@ -1850,50 +1803,6 @@ elf32_sparc_finish_dynamic_sections (output_bfd, info)
 
   elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
 
-  if (info->shared)
-    {
-      asection *sdynsym;
-      asection *s;
-      Elf_Internal_Sym sym;
-      int c;
-
-      /* Set up the section symbols for the output sections.  */
-
-      sdynsym = bfd_get_section_by_name (dynobj, ".dynsym");
-      BFD_ASSERT (sdynsym != NULL);
-
-      sym.st_size = 0;
-      sym.st_name = 0;
-      sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
-      sym.st_other = 0;
-
-      c = 0;
-      for (s = output_bfd->sections; s != NULL; s = s->next)
-       {
-         int indx;
-
-         if (elf_section_data (s)->dynindx == 0)
-           continue;
-
-         sym.st_value = s->vma;
-
-         indx = elf_section_data (s)->this_idx;
-         BFD_ASSERT (indx > 0);
-         sym.st_shndx = indx;
-
-         bfd_elf32_swap_symbol_out (output_bfd, &sym,
-                                    (PTR) (((Elf32_External_Sym *)
-                                            sdynsym->contents)
-                                           + elf_section_data (s)->dynindx));
-
-         ++c;
-       }
-
-      /* Set the sh_info field of the output .dynsym section to the
-         index of the first global symbol.  */
-      elf_section_data (sdynsym->output_section)->this_hdr.sh_info = c + 1;
-    }
-
   return true;
 }
 \f
index a8a7c40..2a0cdb5 100644 (file)
@@ -115,8 +115,6 @@ static boolean elf64_alpha_adjust_dynamic_symbol
   PARAMS((struct bfd_link_info *, struct elf_link_hash_entry *));
 static boolean elf64_alpha_size_dynamic_sections
   PARAMS((bfd *, struct bfd_link_info *));
-static boolean elf64_alpha_adjust_dynindx
-  PARAMS((struct elf_link_hash_entry *, PTR));
 static boolean elf64_alpha_relocate_section
   PARAMS((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
          Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
@@ -3264,34 +3262,6 @@ elf64_alpha_size_dynamic_sections (output_bfd, info)
        }
     }
 
-  /* If we are generating a shared library, we generate a section
-     symbol for each output section.  These are local symbols, which
-     means that they must come first in the dynamic symbol table.
-     That means we must increment the dynamic symbol index of every
-     other dynamic symbol.  */
-  if (info->shared)
-    {
-      long c[2], i;
-      asection *p;
-
-      c[0] = 0;
-      c[1] = bfd_count_sections (output_bfd);
-
-      elf_hash_table (info)->dynsymcount += c[1];
-      elf_link_hash_traverse (elf_hash_table(info),
-                             elf64_alpha_adjust_dynindx,
-                             (PTR) c);
-
-      for (i = 1, p = output_bfd->sections;
-          p != NULL;
-          p = p->next, i++)
-       {
-         elf_section_data (p)->dynindx = i;
-         /* These symbols will have no names, so we don't need to
-            fiddle with dynstr_index.  */
-       }
-    }
-
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       /* Add some entries to the .dynamic section.  We fill in the
@@ -3332,22 +3302,6 @@ elf64_alpha_size_dynamic_sections (output_bfd, info)
   return true;
 }
 
-/* Increment the index of a dynamic symbol by a given amount.  Called
-   via elf_link_hash_traverse.  */
-
-static boolean
-elf64_alpha_adjust_dynindx (h, cparg)
-     struct elf_link_hash_entry *h;
-     PTR cparg;
-{
-  long *cp = (long *)cparg;
-
-  if (h->dynindx >= cp[0])
-    h->dynindx += cp[1];
-
-  return true;
-}
-
 /* Relocate an Alpha ELF section.  */
 
 static boolean
@@ -3991,44 +3945,6 @@ elf64_alpha_finish_dynamic_sections (output_bfd, info)
        }
     }
 
-  if (info->shared)
-    {
-      asection *sdynsym;
-      asection *s;
-      Elf_Internal_Sym sym;
-
-      /* Set up the section symbols for the output sections.  */
-
-      sdynsym = bfd_get_section_by_name (dynobj, ".dynsym");
-      BFD_ASSERT (sdynsym != NULL);
-
-      sym.st_size = 0;
-      sym.st_name = 0;
-      sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
-      sym.st_other = 0;
-
-      for (s = output_bfd->sections; s != NULL; s = s->next)
-       {
-         int indx;
-
-         sym.st_value = s->vma;
-
-         indx = elf_section_data (s)->this_idx;
-         BFD_ASSERT (indx > 0);
-         sym.st_shndx = indx;
-
-         bfd_elf64_swap_symbol_out (output_bfd, &sym,
-                                    (PTR) (((Elf64_External_Sym *)
-                                            sdynsym->contents)
-                                           + elf_section_data (s)->dynindx));
-       }
-
-      /* Set the sh_info field of the output .dynsym section to the
-         index of the first global symbol.  */
-      elf_section_data (sdynsym->output_section)->this_hdr.sh_info =
-       bfd_count_sections (output_bfd) + 1;
-    }
-
   return true;
 }
 
index def6bce..353cdaf 100644 (file)
@@ -51,8 +51,6 @@ static boolean sparc64_elf_adjust_dynamic_symbol
   PARAMS((struct bfd_link_info *, struct elf_link_hash_entry *));
 static boolean sparc64_elf_size_dynamic_sections
   PARAMS((bfd *, struct bfd_link_info *));
-static boolean sparc64_elf_adjust_dynindx
-  PARAMS((struct elf_link_hash_entry *, PTR));
 
 static boolean sparc64_elf_merge_private_bfd_data
   PARAMS ((bfd *, bfd *));
@@ -1146,54 +1144,8 @@ sparc64_elf_size_dynamic_sections (output_bfd, info)
        }
     }
 
-  /* If we are generating a shared library, we generate a section
-     symbol for each output section for which we might need to copy
-     relocs.  These are local symbols, which means that they must come
-     first in the dynamic symbol table.  That means we must increment
-     the dynamic symbol index of every other dynamic symbol.  */
-  if (info->shared)
-    {
-      int c;
-
-      c = 0;
-      for (s = output_bfd->sections; s != NULL; s = s->next)
-       {
-         if ((s->flags & SEC_LINKER_CREATED) != 0
-             || (s->flags & SEC_ALLOC) == 0)
-           continue;
-
-         elf_section_data (s)->dynindx = c + 1;
-
-         /* These symbols will have no names, so we don't need to
-             fiddle with dynstr_index.  */
-
-         ++c;
-       }
-
-      elf_link_hash_traverse (elf_hash_table (info),
-                             sparc64_elf_adjust_dynindx,
-                             (PTR) &c);
-      elf_hash_table (info)->dynsymcount += c;
-    }
-
-  return true;
-}
-
-/* Increment the index of a dynamic symbol by a given amount.  Called
-   via elf_link_hash_traverse.  */
-
-static boolean
-sparc64_elf_adjust_dynindx (h, cparg)
-     struct elf_link_hash_entry *h;
-     PTR cparg;
-{
-  int *cp = (int *) cparg;
-
-  if (h->dynindx != -1)
-    h->dynindx += *cp;
   return true;
 }
-
 \f
 /* Relocate a SPARC64 ELF section.  */
 
@@ -2090,50 +2042,6 @@ sparc64_elf_finish_dynamic_sections (output_bfd, info)
 
   elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 8;
 
-  if (info->shared)
-    {
-      asection *sdynsym;
-      asection *s;
-      Elf_Internal_Sym sym;
-      int c;
-
-      /* Set up the section symbols for the output sections.  */
-
-      sdynsym = bfd_get_section_by_name (dynobj, ".dynsym");
-      BFD_ASSERT (sdynsym != NULL);
-
-      sym.st_size = 0;
-      sym.st_name = 0;
-      sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
-      sym.st_other = 0;
-
-      c = 0;
-      for (s = output_bfd->sections; s != NULL; s = s->next)
-       {
-         int indx;
-
-         if (elf_section_data (s)->dynindx == 0)
-           continue;
-
-         sym.st_value = s->vma;
-
-         indx = elf_section_data (s)->this_idx;
-         BFD_ASSERT (indx > 0);
-         sym.st_shndx = indx;
-
-         bfd_elf64_swap_symbol_out (output_bfd, &sym,
-                                    (PTR) (((Elf64_External_Sym *)
-                                            sdynsym->contents)
-                                           + elf_section_data (s)->dynindx));
-
-         ++c;
-       }
-
-      /* Set the sh_info field of the output .dynsym section to the
-         index of the first global symbol.  */
-      elf_section_data (sdynsym->output_section)->this_hdr.sh_info = c + 1;
-    }
-
   return true;
 }
 \f
index 49e156e..adbafd8 100644 (file)
@@ -130,6 +130,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #define elf_gc_common_final_link       NAME(_bfd_elf,gc_common_final_link)
 #define elf_gc_record_vtinherit                NAME(_bfd_elf,gc_record_vtinherit)
 #define elf_gc_record_vtentry          NAME(_bfd_elf,gc_record_vtentry)
+#define elf_link_record_local_dynamic_symbol \
+  NAME(_bfd_elf,link_record_local_dynamic_symbol)
 
 #if ARCH_SIZE == 64
 #define ELF_R_INFO(X,Y)        ELF64_R_INFO(X,Y)
index e26dedd..93155b1 100644 (file)
@@ -260,22 +260,83 @@ _bfd_elf_link_record_dynamic_symbol (info, h)
   return true;
 }
 
-/* Increase the index at which H will appear in the dynamic symbol
-   table by INCREMENT (which is really an `int *').  Called via
-   elf_link_hash_traverse.  */
+/* Return the dynindex of a local dynamic symbol.  */
 
-boolean
-_bfd_elf_link_adjust_dynindx (h, increment)
+long
+_bfd_elf_link_lookup_local_dynindx (info, input_bfd, input_indx)
+     struct bfd_link_info *info;
+     bfd *input_bfd;
+     long input_indx;
+{
+  struct elf_link_local_dynamic_entry *e;
+
+  for (e = elf_hash_table (info)->dynlocal; e ; e = e->next)
+    if (e->input_bfd == input_bfd && e->input_indx == input_indx)
+      return e->dynindx;
+  return -1;
+}
+
+/* This function is used to renumber the dynamic symbols, if some of
+   them are removed because they are marked as local.  This is called
+   via elf_link_hash_traverse.  */
+
+static boolean elf_link_renumber_hash_table_dynsyms
+  PARAMS ((struct elf_link_hash_entry *, PTR));
+
+static boolean
+elf_link_renumber_hash_table_dynsyms (h, data)
      struct elf_link_hash_entry *h;
-     PTR increment;
+     PTR data;
 {
+  size_t *count = (size_t *) data;
+
   if (h->dynindx != -1)
-    h->dynindx += *((int *) increment);
-    
+    h->dynindx = ++(*count);
+
   return true;
 }
+
+/* Assign dynsym indicies.  In a shared library we generate a section
+   symbol for each output section, which come first.  Next come all of
+   the back-end allocated local dynamic syms, followed by the rest of
+   the global symbols.  */
+
+unsigned long
+_bfd_elf_link_renumber_dynsyms (output_bfd, info)
+     bfd *output_bfd;
+     struct bfd_link_info *info;
+{
+  unsigned long dynsymcount = 0;
+
+  if (info->shared)
+    {
+      asection *p;
+      for (p = output_bfd->sections; p ; p = p->next)
+       elf_section_data (p)->dynindx = ++dynsymcount;
+    }
+
+  if (elf_hash_table (info)->dynlocal)
+    {
+      struct elf_link_local_dynamic_entry *p;
+      for (p = elf_hash_table (info)->dynlocal; p ; p = p->next)
+       p->dynindx = ++dynsymcount;
+    }
+
+  elf_link_hash_traverse (elf_hash_table (info),
+                         elf_link_renumber_hash_table_dynsyms,
+                         &dynsymcount);
+
+  /* There is an unused NULL entry at the head of the table which
+     we must account for in our count.  Unless there weren't any
+     symbols, which means we'll have no table at all.  */
+  if (dynsymcount != 0)
+    ++dynsymcount;
+
+  return elf_hash_table (info)->dynsymcount = dynsymcount;
+}
 \f
-/* Create a special linker section, or return a pointer to a linker section already created  */
+/* Create a special linker section, or return a pointer to a linker
+   section already created */
 
 elf_linker_section_t *
 _bfd_elf_create_linker_section (abfd, info, which, defaults)
index 26fee85..bf73759 100644 (file)
@@ -48,14 +48,10 @@ static boolean elf_link_find_version_dependencies
   PARAMS ((struct elf_link_hash_entry *, PTR));
 static boolean elf_link_assign_sym_version
   PARAMS ((struct elf_link_hash_entry *, PTR));
-static boolean elf_link_renumber_dynsyms
-  PARAMS ((struct elf_link_hash_entry *, PTR));
 static boolean elf_collect_hash_codes
   PARAMS ((struct elf_link_hash_entry *, PTR));
 static boolean elf_link_read_relocs_from_section 
   PARAMS ((bfd *, Elf_Internal_Shdr *, PTR, Elf_Internal_Rela *));
-static void elf_link_remove_section_and_adjust_dynindices 
-  PARAMS ((struct bfd_link_info *, asection *));
 static void elf_link_output_relocs
   PARAMS ((bfd *, asection *, Elf_Internal_Shdr *, Elf_Internal_Rela *));
 static boolean elf_link_size_reloc_section
@@ -2051,6 +2047,73 @@ 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 bfd_strtab_hash *dynstr;
+  Elf_External_Sym esym;
+  unsigned long dynstr_index;
+  char *name;
+  int elfsec, link;
+
+  /* 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, sizeof (*entry));
+  if (entry == NULL)
+    return false;
+
+  /* Go find the symbol, so that we can find it's name.  */
+  if (bfd_seek (input_bfd,
+               (elf_tdata (input_bfd)->symtab_hdr.sh_offset
+                + input_indx * sizeof (Elf_External_Sym)),
+               SEEK_SET) != 0
+      || (bfd_read (&esym, sizeof (Elf_External_Sym), 1, input_bfd)
+         != sizeof (Elf_External_Sym)))
+    return false;
+  elf_swap_symbol_in (input_bfd, &esym, &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_stringtab_init ();
+      if (dynstr == NULL)
+       return false;
+    }
+
+  dynstr_index = _bfd_stringtab_add (dynstr, name, true, 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++;
+
+  /* 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
@@ -2310,8 +2373,6 @@ struct elf_assign_sym_version_info
   struct bfd_elf_version_tree *verdefs;
   /* Whether we are exporting all dynamic symbols.  */
   boolean export_dynamic;
-  /* Whether we removed any symbols from the dynamic symbol table.  */
-  boolean removed_dynamic;
   /* Whether we had a failure.  */
   boolean failed;
 };
@@ -2486,42 +2547,6 @@ compute_bucket_count (info)
   return best_size;
 }
 
-/* Remove SECTION from the BFD.  If a symbol for SECTION was going to
-   be put into the dynamic symbol table, remove it, and renumber
-   subsequent entries.  */
-
-static void
-elf_link_remove_section_and_adjust_dynindices (info, section)
-     struct bfd_link_info *info;
-     asection *section;
-{
-  /* Remove the section from the output list.  */
-  _bfd_strip_section_from_output (section);
-
-  if (elf_section_data (section->output_section)->dynindx)
-    {
-      asection *s;
-      int increment = -1;
-
-      /* We were going to output an entry in the dynamic symbol table
-        for the symbol corresponding to this section.  Now, the
-        section is gone.  So, we must renumber the dynamic indices of
-        all subsequent sections and all other entries in the dynamic
-        symbol table.  */
-      elf_section_data (section->output_section)->dynindx = 0;
-      for (s = section->output_section->next; s; s = s->next)
-       if (elf_section_data (s)->dynindx)
-         --elf_section_data (s)->dynindx;
-      
-      elf_link_hash_traverse (elf_hash_table (info),
-                             _bfd_elf_link_adjust_dynindx,
-                             &increment);
-
-      /* There is one less dynamic symbol than there was before.  */
-      --elf_hash_table (info)->dynsymcount;
-    }
-}
-
 /* Set up the sizes and contents of the ELF dynamic sections.  This is
    called by the ELF linker emulation before_allocation routine.  We
    must set the sizes of the sections before the linker sets the
@@ -2545,7 +2570,6 @@ 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;
   struct elf_assign_sym_version_info asvinfo;
 
   *sinterpptr = NULL;
@@ -2650,7 +2674,6 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
       asvinfo.info = info;
       asvinfo.verdefs = verdefs;
       asvinfo.export_dynamic = export_dynamic;
-      asvinfo.removed_dynamic = false;
       asvinfo.failed = false;
 
       elf_link_hash_traverse (elf_hash_table (info),
@@ -2712,7 +2735,6 @@ 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
       && ! (*bed->elf_backend_size_dynamic_sections) (output_bfd, info))
     return false;
@@ -2734,7 +2756,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
       verdefs = asvinfo.verdefs;
 
       if (verdefs == NULL)
-       elf_link_remove_section_and_adjust_dynindices (info, s);
+       _bfd_strip_section_from_output (s);
       else
        {
          unsigned int cdefs;
@@ -2744,23 +2766,6 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
          Elf_Internal_Verdef def;
          Elf_Internal_Verdaux defaux;
 
-         if (asvinfo.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.  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);
-           }
-
          cdefs = 0;
          size = 0;
 
@@ -2927,7 +2932,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
                                (PTR) &sinfo);
 
        if (elf_tdata (output_bfd)->verref == NULL)
-         elf_link_remove_section_and_adjust_dynindices (info, s);
+         _bfd_strip_section_from_output (s);
        else
          {
            Elf_Internal_Verneed *t;
@@ -3018,7 +3023,12 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
          }
       }
 
-      dynsymcount = elf_hash_table (info)->dynsymcount;
+      /* Assign dynsym indicies.  In a shared library we generate a 
+        section symbol for each output section, which come first.
+        Next come all of the back-end allocated local dynamic syms,
+        followed by the rest of the global symbols.  */
+
+      dynsymcount = _bfd_elf_link_renumber_dynsyms (output_bfd, info);
 
       /* Work out the size of the symbol version section.  */
       s = bfd_get_section_by_name (dynobj, ".gnu.version");
@@ -3026,10 +3036,10 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
       if (dynsymcount == 0
          || (verdefs == NULL && elf_tdata (output_bfd)->verref == NULL))
        {
-         elf_link_remove_section_and_adjust_dynindices (info, s);
+         _bfd_strip_section_from_output (s);
          /* The DYNSYMCOUNT might have changed if we were going to
             output a dynamic symbol table entry for S.  */
-         dynsymcount = elf_hash_table (info)->dynsymcount;
+         dynsymcount = _bfd_elf_link_renumber_dynsyms (output_bfd, info);
        }
       else
        {
@@ -3513,7 +3523,6 @@ elf_link_assign_sym_version (h, data)
                              && info->shared
                              && ! sinfo->export_dynamic)
                            {
-                             sinfo->removed_dynamic = true;
                              h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL;
                              h->elf_link_hash_flags &=~
                                ELF_LINK_HASH_NEEDS_PLT;
@@ -3629,7 +3638,6 @@ elf_link_assign_sym_version (h, data)
                          && info->shared
                          && ! sinfo->export_dynamic)
                        {
-                         sinfo->removed_dynamic = true;
                          h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL;
                          h->elf_link_hash_flags &=~ ELF_LINK_HASH_NEEDS_PLT;
                          h->dynindx = -1;
@@ -3654,7 +3662,6 @@ elf_link_assign_sym_version (h, data)
              && info->shared
              && ! sinfo->export_dynamic)
            {
-             sinfo->removed_dynamic = true;
              h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL;
              h->elf_link_hash_flags &=~ ELF_LINK_HASH_NEEDS_PLT;
              h->dynindx = -1;
@@ -3667,26 +3674,6 @@ elf_link_assign_sym_version (h, data)
 
   return true;
 }
-
-/* This function is used to renumber the dynamic symbols, if some of
-   them are removed because they are marked as local.  This is called
-   via elf_link_hash_traverse.  */
-
-static boolean
-elf_link_renumber_dynsyms (h, data)
-     struct elf_link_hash_entry *h;
-     PTR data;
-{
-  struct bfd_link_info *info = (struct bfd_link_info *) data;
-
-  if (h->dynindx != -1)
-    {
-      h->dynindx = elf_hash_table (info)->dynsymcount;
-      ++elf_hash_table (info)->dynsymcount;
-    }
-
-  return true;
-}
 \f
 /* Final phase of ELF linker.  */
 
@@ -4161,11 +4148,77 @@ elf_bfd_final_link (abfd, info)
        return false;
     }
 
-  /* The sh_info field records the index of the first non local
-     symbol.  */
+  /* The sh_info field records the index of the first non local symbol.  */
   symtab_hdr->sh_info = bfd_get_symcount (abfd);
+
   if (dynamic)
-    elf_section_data (finfo.dynsym_sec->output_section)->this_hdr.sh_info = 1;
+    {
+      Elf_Internal_Sym sym;
+      Elf_External_Sym *dynsym =
+       (Elf_External_Sym *)finfo.dynsym_sec->contents;
+      unsigned long last_local = 0;
+
+      /* Write out the section symbols for the output sections.  */
+      if (info->shared)
+       {
+         asection *s;
+
+         sym.st_size = 0;
+         sym.st_name = 0;
+         sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
+         sym.st_other = 0;
+
+         for (s = abfd->sections; s != NULL; s = s->next)
+           {
+             int indx;
+             indx = elf_section_data (s)->this_idx;
+             BFD_ASSERT (indx > 0);
+             sym.st_shndx = indx;
+             sym.st_value = s->vma;
+
+             elf_swap_symbol_out (abfd, &sym,
+                                  dynsym + elf_section_data (s)->dynindx);
+           }
+
+         last_local = bfd_count_sections (abfd);
+       }
+
+      /* Write out the local dynsyms.  */
+      if (elf_hash_table (info)->dynlocal)
+       {
+         struct elf_link_local_dynamic_entry *e;
+         for (e = elf_hash_table (info)->dynlocal; e ; e = e->next)
+           {
+             asection *s, *os;
+
+             sym.st_size = e->isym.st_size;
+             sym.st_other = e->isym.st_other;
+
+             /* Note that we saved a word of storage and overwrote
+                 the original st_name with the dynstr_index.  */
+             sym.st_name = e->isym.st_name;
+
+             /* Whatever binding the symbol had before, it's now local.  */
+             sym.st_info = ELF_ST_INFO (STB_LOCAL,
+                                        ELF_ST_TYPE (e->isym.st_info));
+
+             s = bfd_section_from_elf_index (e->input_bfd, e->isym.st_shndx);
+
+             sym.st_shndx = elf_section_data (s->output_section)->this_idx;
+             sym.st_value = (s->output_section->vma
+                             + s->output_offset
+                             + e->isym.st_value);
+
+             if (last_local < e->dynindx)
+               last_local = e->dynindx;
+
+             elf_swap_symbol_out (abfd, &sym, dynsym + e->dynindx);
+           }
+       }
+
+      elf_section_data (finfo.dynsym_sec->output_section)
+       ->this_hdr.sh_info = last_local;
+    }
 
   /* We get the global symbols from the hash table.  */
   eoinfo.failed = false;