* libelf.h (struct bfd_elf_section_data): Add field dynindx.
authorIan Lance Taylor <ian@airs.com>
Thu, 27 Oct 1994 21:25:31 +0000 (21:25 +0000)
committerIan Lance Taylor <ian@airs.com>
Thu, 27 Oct 1994 21:25:31 +0000 (21:25 +0000)
* elfcode.h (NAME(bfd_elf,size_dynamic_sections)): Don't finalize
the .dynsym, .dynstr or .hash sections until after the backend
size_dynamic_sections routine, so that it can add dynamic symbols
if it wants to.
* elf32-i386.c (elf_i386_adjust_dynamic_symbol): Don't define the
symbol to be in the .plt section when generating a shared library
if it is a defined symbol.
* elf32-sparc.c (elf32_sparc_adjust_dynamic_symbol): Likewise.
(elf32_sparc_size_dynamic_sections): When generating a shared
library, allocate space for a dynamic symbol for each output
section, storing the index in the dynindx field of the ELF section
data.  Adjust the other dynindx fields to account for this.
(elf32_sparc_adjust_dynindx): New static function.
(elf32_sparc_relocate_section): When copying a reloc into a shared
library, use the original addend as appropriate.  Convert an
R_SPARC_32 reloc into an R_SPARC_RELATIVE reloc.  Use the dynamic
symbol index of the output section, not the normal symbol index.
(elf32_sparc_finish_dynamic_sections): Don't die if a section does
not exist when setting the value of the dynamic tags.  Write out
a dynamic symbol for each output section.

bfd/ChangeLog
bfd/elf32-i386.c
bfd/elf32-sparc.c
bfd/elfcode.h
bfd/libelf.h

index 2c1e06689b2ef58bc8ecd4e84ab382cdcb12256c..414ef4076146f73137c7358a7dd80003f2097f63 100644 (file)
@@ -1,3 +1,27 @@
+Thu Oct 27 16:59:52 1994  Ian Lance Taylor  <ian@sanguine.cygnus.com>
+
+       * libelf.h (struct bfd_elf_section_data): Add field dynindx.
+       * elfcode.h (NAME(bfd_elf,size_dynamic_sections)): Don't finalize
+       the .dynsym, .dynstr or .hash sections until after the backend
+       size_dynamic_sections routine, so that it can add dynamic symbols
+       if it wants to.
+       * elf32-i386.c (elf_i386_adjust_dynamic_symbol): Don't define the
+       symbol to be in the .plt section when generating a shared library
+       if it is a defined symbol.
+       * elf32-sparc.c (elf32_sparc_adjust_dynamic_symbol): Likewise.
+       (elf32_sparc_size_dynamic_sections): When generating a shared
+       library, allocate space for a dynamic symbol for each output
+       section, storing the index in the dynindx field of the ELF section
+       data.  Adjust the other dynindx fields to account for this.
+       (elf32_sparc_adjust_dynindx): New static function.
+       (elf32_sparc_relocate_section): When copying a reloc into a shared
+       library, use the original addend as appropriate.  Convert an
+       R_SPARC_32 reloc into an R_SPARC_RELATIVE reloc.  Use the dynamic
+       symbol index of the output section, not the normal symbol index.
+       (elf32_sparc_finish_dynamic_sections): Don't die if a section does
+       not exist when setting the value of the dynamic tags.  Write out
+       a dynamic symbol for each output section.
+
 Wed Oct 26 01:15:51 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
 
        * aoutx.h (aout_link_input_section): Don't bother to read or write
index 14f4b7165597bc5acbea53e6df79c4509cc41651..60c0f45b6749c9b4b57b91219f30dcfd172cd746 100644 (file)
@@ -542,9 +542,9 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
          if (info->shared
              && (sec->flags & SEC_ALLOC) != 0)
            {
-             /* When creating a shared object, we must output a
-                 R_386_RELATIVE reloc for this location.  We create a
-                 reloc section in dynobj and make room for this reloc.  */
+             /* When creating a shared object, we must copy these
+                 reloc types into the output file.  We create a reloc
+                 section in dynobj and make room for this reloc.  */
              if (sreloc == NULL)
                {
                  const char *name;
@@ -647,9 +647,15 @@ elf_i386_adjust_dynamic_symbol (info, h)
       if (s->_raw_size == 0)
        s->_raw_size += PLT_ENTRY_SIZE;
 
-      /* Set the symbol to this location in the .plt.  */
-      h->root.u.def.section = s;
-      h->root.u.def.value = s->_raw_size;
+      /* If we are not generating a shared library, or if the symbol
+         is not defined, set the symbol to this location in the .plt.
+         This is required to make function pointers compare as equal
+         between the normal executable and the shared library.  */
+      if (! info->shared || h->root.type != bfd_link_hash_defined)
+       {
+         h->root.u.def.section = s;
+         h->root.u.def.value = s->_raw_size;
+       }
 
       h->plt_offset = s->_raw_size;
 
index 90130ccab23c4ae402769319e7dffc0f3782bcae..713e8555844834f4cf440c03415c6297cdb54898 100644 (file)
@@ -36,6 +36,8 @@ 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
@@ -617,9 +619,15 @@ elf32_sparc_adjust_dynamic_symbol (info, h)
          return false;
        }
 
-      /* Set the symbol to this location in the .plt.  */
-      h->root.u.def.section = s;
-      h->root.u.def.value = s->_raw_size;
+      /* If we are not generating a shared library, or if the symbol
+         is not defined, set the symbol to this location in the .plt.
+         This is required to make function pointers compare as equal
+         between the normal executable and the shared library.  */
+      if (! info->shared || h->root.type != bfd_link_hash_defined)
+       {
+         h->root.u.def.section = s;
+         h->root.u.def.value = s->_raw_size;
+       }
 
       h->plt_offset = s->_raw_size;
 
@@ -863,6 +871,44 @@ elf32_sparc_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)
+    {
+      int c, i;
+
+      c = bfd_count_sections (output_bfd);
+      elf_link_hash_traverse (elf_hash_table (info),
+                             elf32_sparc_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;
+}
+
+/* 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;
 }
 
@@ -1146,37 +1192,44 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
                {
                  BFD_ASSERT (h->dynindx != -1);
                  outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
-                 outrel.r_addend = 0;
+                 outrel.r_addend = rel->r_addend;
                }
              else
                {
-                 long indx;
-
-                 sym = local_syms + r_symndx;
-
-                 /* If this isn't a section symbol, we need to map it
-                     to something that is going to be put into the
-                     dynamic symbols.  The case will probably never
-                     arise.  */
-                 BFD_ASSERT (ELF_ST_TYPE (sym->st_info) == STT_SECTION);
-
-                 sec = local_sections[r_symndx];
-                 if (sec != NULL && bfd_is_abs_section (sec))
-                   indx = 0;
-                 else if (sec == NULL || sec->owner == NULL)
+                 if (r_type == R_SPARC_32)
                    {
-                     bfd_set_error (bfd_error_bad_value);
-                     return false;
+                     outrel.r_info = ELF32_R_INFO (0, R_SPARC_RELATIVE);
+                     outrel.r_addend = relocation + rel->r_addend;
                    }
                  else
                    {
-                     indx = sec->output_section->target_index;
-                     if (indx == 0)
-                       abort ();
+                     long indx;
+
+                     sym = local_syms + r_symndx;
+
+                     BFD_ASSERT (ELF_ST_TYPE (sym->st_info) == STT_SECTION);
+
+                     sec = local_sections[r_symndx];
+                     if (sec != NULL && bfd_is_abs_section (sec))
+                       indx = 0;
+                     else if (sec == NULL || sec->owner == NULL)
+                       {
+                         bfd_set_error (bfd_error_bad_value);
+                         return false;
+                       }
+                     else
+                       {
+                         asection *osec;
+
+                         osec = sec->output_section;
+                         indx = elf_section_data (osec)->dynindx;
+                         if (indx == 0)
+                           abort ();
+                       }
+
+                     outrel.r_info = ELF32_R_INFO (indx, r_type);
+                     outrel.r_addend = relocation + rel->r_addend;
                    }
-
-                 outrel.r_info = ELF32_R_INFO (indx, r_type);
-                 outrel.r_addend = sec->output_offset + sym->st_value;
                }
 
              bfd_elf32_swap_reloca_out (output_bfd, &outrel,
@@ -1399,15 +1452,19 @@ elf32_sparc_finish_dynamic_sections (output_bfd, info)
              asection *s;
 
              s = bfd_get_section_by_name (output_bfd, name);
-             BFD_ASSERT (s != NULL);
-             if (! size)
-               dyn.d_un.d_ptr = s->vma;
+             if (s == NULL)
+               dyn.d_un.d_val = 0;
              else
                {
-                 if (s->_cooked_size != 0)
-                   dyn.d_un.d_val = s->_cooked_size;
+                 if (! size)
+                   dyn.d_un.d_ptr = s->vma;
                  else
-                   dyn.d_un.d_val = s->_raw_size;
+                   {
+                     if (s->_cooked_size != 0)
+                       dyn.d_un.d_val = s->_cooked_size;
+                     else
+                       dyn.d_un.d_val = s->_raw_size;
+                   }
                }
              bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
            }
@@ -1442,6 +1499,43 @@ 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;
+
+      /* 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_elf32_swap_symbol_out (output_bfd, &sym,
+                                    ((Elf32_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 d1ef2dc494bd8a81b81d84d8ca57c2891dee1f2d..cdb51afda88dc43cd7d2a5b3dc9e6a243a145a54 100644 (file)
@@ -4819,62 +4819,11 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, info,
 
   if (elf_hash_table (info)->dynamic_sections_created)
     {
-      size_t dynsymcount;
       bfd_size_type strsize;
 
       *sinterpptr = bfd_get_section_by_name (dynobj, ".interp");
       BFD_ASSERT (*sinterpptr != NULL || info->shared);
 
-      /* Set the size of the .dynsym and .hash sections.  We counted
-        the number of dynamic symbols in elf_link_add_object_symbols.
-        We will build the contents of .dynsym and .hash when we build
-        the final symbol table, because until then we do not know the
-        correct value to give the symbols.  We built the .dynstr
-        section as we went along in elf_link_add_object_symbols.  */
-      dynsymcount = elf_hash_table (info)->dynsymcount;
-      s = bfd_get_section_by_name (dynobj, ".dynsym");
-      BFD_ASSERT (s != NULL);
-      s->_raw_size = dynsymcount * sizeof (Elf_External_Sym);
-      s->contents = (bfd_byte *) bfd_alloc (output_bfd, s->_raw_size);
-      if (s->contents == NULL && s->_raw_size != 0)
-       {
-         bfd_set_error (bfd_error_no_memory);
-         return false;
-       }
-
-      /* The first entry in .dynsym is a dummy symbol.  */
-      isym.st_value = 0;
-      isym.st_size = 0;
-      isym.st_name = 0;
-      isym.st_info = 0;
-      isym.st_other = 0;
-      isym.st_shndx = 0;
-      elf_swap_symbol_out (output_bfd, &isym,
-                          (Elf_External_Sym *) s->contents);
-
-      for (i = 0; elf_buckets[i] != 0; i++)
-       {
-         bucketcount = elf_buckets[i];
-         if (dynsymcount < elf_buckets[i + 1])
-           break;
-       }
-
-      s = bfd_get_section_by_name (dynobj, ".hash");
-      BFD_ASSERT (s != NULL);
-      s->_raw_size = (2 + bucketcount + dynsymcount) * (ARCH_SIZE / 8);
-      s->contents = (bfd_byte *) bfd_alloc (output_bfd, s->_raw_size);
-      if (s->contents == NULL)
-       {
-         bfd_set_error (bfd_error_no_memory);
-         return false;
-       }
-      memset (s->contents, 0, s->_raw_size);
-
-      put_word (output_bfd, bucketcount, s->contents);
-      put_word (output_bfd, dynsymcount, s->contents + (ARCH_SIZE / 8));
-
-      elf_hash_table (info)->bucketcount = bucketcount;
-
       if (soname != NULL)
        {
          bfd_size_type indx;
@@ -4897,10 +4846,6 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, info,
            return false;
        }
 
-      s = bfd_get_section_by_name (dynobj, ".dynstr");
-      BFD_ASSERT (s != NULL);
-      s->_raw_size = _bfd_stringtab_size (elf_hash_table (info)->dynstr);
-
       /* 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),
@@ -4938,6 +4883,62 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, info,
 
   if (elf_hash_table (info)->dynamic_sections_created)
     {
+      size_t dynsymcount;
+
+      /* Set the size of the .dynsym and .hash sections.  We counted
+        the number of dynamic symbols in elf_link_add_object_symbols.
+        We will build the contents of .dynsym and .hash when we build
+        the final symbol table, because until then we do not know the
+        correct value to give the symbols.  We built the .dynstr
+        section as we went along in elf_link_add_object_symbols.  */
+      dynsymcount = elf_hash_table (info)->dynsymcount;
+      s = bfd_get_section_by_name (dynobj, ".dynsym");
+      BFD_ASSERT (s != NULL);
+      s->_raw_size = dynsymcount * sizeof (Elf_External_Sym);
+      s->contents = (bfd_byte *) bfd_alloc (output_bfd, s->_raw_size);
+      if (s->contents == NULL && s->_raw_size != 0)
+       {
+         bfd_set_error (bfd_error_no_memory);
+         return false;
+       }
+
+      /* The first entry in .dynsym is a dummy symbol.  */
+      isym.st_value = 0;
+      isym.st_size = 0;
+      isym.st_name = 0;
+      isym.st_info = 0;
+      isym.st_other = 0;
+      isym.st_shndx = 0;
+      elf_swap_symbol_out (output_bfd, &isym,
+                          (Elf_External_Sym *) s->contents);
+
+      for (i = 0; elf_buckets[i] != 0; i++)
+       {
+         bucketcount = elf_buckets[i];
+         if (dynsymcount < elf_buckets[i + 1])
+           break;
+       }
+
+      s = bfd_get_section_by_name (dynobj, ".hash");
+      BFD_ASSERT (s != NULL);
+      s->_raw_size = (2 + bucketcount + dynsymcount) * (ARCH_SIZE / 8);
+      s->contents = (bfd_byte *) bfd_alloc (output_bfd, s->_raw_size);
+      if (s->contents == NULL)
+       {
+         bfd_set_error (bfd_error_no_memory);
+         return false;
+       }
+      memset (s->contents, 0, s->_raw_size);
+
+      put_word (output_bfd, bucketcount, s->contents);
+      put_word (output_bfd, dynsymcount, s->contents + (ARCH_SIZE / 8));
+
+      elf_hash_table (info)->bucketcount = bucketcount;
+
+      s = bfd_get_section_by_name (dynobj, ".dynstr");
+      BFD_ASSERT (s != NULL);
+      s->_raw_size = _bfd_stringtab_size (elf_hash_table (info)->dynstr);
+
       if (! elf_add_dynamic_entry (info, DT_NULL, 0))
        return false;
     }
index b752946b31a84552637ab743dd37f71852ebc602..3bbde899623fdaf3b2942046f0d2f52d14f95091 100644 (file)
@@ -420,6 +420,10 @@ struct bfd_elf_section_data {
      rather than RELA, all the r_addend fields will be zero.  This
      pointer may be NULL.  It is used by the backend linker.  */
   Elf_Internal_Rela *relocs;
+  /* Used by the backend linker when generating a shared library to
+     record the dynamic symbol index for a section symbol
+     corresponding to this section.  */
+  long dynindx;
 };
 
 #define elf_section_data(sec)  ((struct bfd_elf_section_data*)sec->used_by_bfd)