* elf32-sh.c (elf_sh_link_hash_entry): Add gotplt_refcount.
authorStephen Clarke <stephen.clarke@earthling.net>
Wed, 2 Oct 2002 21:53:40 +0000 (21:53 +0000)
committerStephen Clarke <stephen.clarke@earthling.net>
Wed, 2 Oct 2002 21:53:40 +0000 (21:53 +0000)
(sh_elf_link_hash_newfunc): Initialize it.
(allocate_dynrelocs): Transfer gotplt refs from plt.refcount
to got.refcount for symbols that are forced local or when
we have direct got refs.
(sh_elf_gc_sweep_hook): Adjust gotplt_refcount.  Use it
to correctly adjust got.refcount and plt.refcount.
(sh_elf_copy_indirect_symbol): Copy gotplt_refcount across.
(sh_elf_check_relocs): Increment gotplt_refcount.

bfd/ChangeLog
bfd/elf32-sh.c

index 90d90d258fbcea1fe323111a00719e0b86bffacb..f2c7a389e31530f3a4559d41b8bf62fe881b6435 100644 (file)
@@ -1,3 +1,15 @@
+2002-10-02  Stephen Clarke <stephen.clarke@superh.com>
+
+       * elf32-sh.c (elf_sh_link_hash_entry): Add gotplt_refcount.
+       (sh_elf_link_hash_newfunc): Initialize it.
+       (allocate_dynrelocs): Transfer gotplt refs from plt.refcount
+       to got.refcount for symbols that are forced local or when
+       we have direct got refs.
+       (sh_elf_gc_sweep_hook): Adjust gotplt_refcount.  Use it
+       to correctly adjust got.refcount and plt.refcount.
+       (sh_elf_copy_indirect_symbol): Copy gotplt_refcount across.
+       (sh_elf_check_relocs): Increment gotplt_refcount.
+       
 2002-10-01  Jakub Jelinek  <jakub@redhat.com>
 
        * elf32-i386.c (elf_i386_relocate_section): Fix
index c8bbe7152dbe10b3251c0cd2291181ce8a79a34a..703ac4016be3e51e80669edb1eab67b0ca544372 100644 (file)
@@ -3388,6 +3388,8 @@ struct elf_sh_link_hash_entry
 
   /* Track dynamic relocs copied for this symbol.  */
   struct elf_sh_dyn_relocs *dyn_relocs;
+
+  bfd_signed_vma gotplt_refcount;
 };
 
 /* sh ELF linker hash table.  */
@@ -3452,6 +3454,7 @@ sh_elf_link_hash_newfunc (entry, table, string)
 
       eh = (struct elf_sh_link_hash_entry *) ret;
       eh->dyn_relocs = NULL;
+      eh->gotplt_refcount = 0;
 #ifdef INCLUDE_SHMEDIA
       ret->datalabel_got_offset = (bfd_vma) -1;
 #endif
@@ -3867,6 +3870,18 @@ allocate_dynrelocs (h, inf)
   info = (struct bfd_link_info *) inf;
   htab = sh_elf_hash_table (info);
 
+  eh = (struct elf_sh_link_hash_entry *) h;
+  if ((h->got.refcount > 0
+      || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL))
+      && eh->gotplt_refcount > 0)
+    {
+      /* The symbol has been forced local, or we have some direct got refs,
+         so treat all the gotplt refs as got refs. */
+      h->got.refcount += eh->gotplt_refcount;
+      if (h->plt.refcount >= eh->gotplt_refcount)
+       h->plt.refcount -= eh->gotplt_refcount;
+    }
+
   if (htab->root.dynamic_sections_created
       && h->plt.refcount > 0)
     {
@@ -3961,7 +3976,6 @@ allocate_dynrelocs (h, inf)
   else
     h->got.offset = (bfd_vma) -1;
 
-  eh = (struct elf_sh_link_hash_entry *) h;
   if (eh->dyn_relocs == NULL)
     return true;
 
@@ -5200,6 +5214,7 @@ sh_elf_gc_sweep_hook (abfd, info, sec, relocs)
   const Elf_Internal_Rela *rel, *relend;
   unsigned long r_symndx;
   struct elf_link_hash_entry *h;
+  struct elf_sh_link_hash_entry *eh;
 
   elf_section_data (sec)->local_dynrel = NULL;
 
@@ -5302,10 +5317,15 @@ sh_elf_gc_sweep_hook (abfd, info, sec, relocs)
        if (r_symndx >= symtab_hdr->sh_info)
          {
            h = sym_hashes[r_symndx - symtab_hdr->sh_info];
-           if (h->got.refcount > 0)
+           eh = (struct elf_sh_link_hash_entry *) h;
+           if (eh->gotplt_refcount > 0)
+             {
+               eh->gotplt_refcount -= 1;
+               if (h->plt.refcount > 0)
+                 h->plt.refcount -= 1;
+             }
+           else if (h->got.refcount > 0)
              h->got.refcount -= 1;
-           if (h->plt.refcount > 0)
-             h->plt.refcount -= 1;
          }
        else if (local_got_refcounts != NULL)
          {
@@ -5365,6 +5385,8 @@ sh_elf_copy_indirect_symbol (bed, dir, ind)
       edir->dyn_relocs = eind->dyn_relocs;
       eind->dyn_relocs = NULL;
     }
+  edir->gotplt_refcount = eind->gotplt_refcount;
+  eind->gotplt_refcount = 0;
 
   _bfd_elf_link_hash_copy_indirect (bed, dir, ind);
 }
@@ -5539,6 +5561,7 @@ sh_elf_check_relocs (abfd, info, sec, relocs)
 
          h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
          h->plt.refcount += 1;
+         ((struct elf_sh_link_hash_entry *) h)->gotplt_refcount += 1;
 
          break;