* elf32-frv.c (struct frv_pic_relocs_info): Added fixups and
authorAlexandre Oliva <aoliva@redhat.com>
Tue, 2 Mar 2004 23:01:18 +0000 (23:01 +0000)
committerAlexandre Oliva <aoliva@redhat.com>
Tue, 2 Mar 2004 23:01:18 +0000 (23:01 +0000)
dynrelocs.
(_frv_count_got_plt_entries): Initialize them.
(frv_pic_relocs_info_find): Add insert argument.  Adjust all
callers.
(frv_pic_relocs_info_for_global): Likewise.
(frv_pic_relocs_info_for_local): Likewise.
(frv_pic_merge_early_relocs_info): New.
(_frv_resolve_final_relocs_info): Use it in case one entry maps to
another.
(_frv_add_dyn_reloc): Add entry argument.  Adjust all callers.
Check that we don't exceed the allocated count for entry.
(_frv_add_rofixup): Likewise.
(_frv_emit_got_relocs_plt_entries): Adjust for coding standards.
(elf32_frv_finish_dynamic_sections): Improve error message in case
we emit too few rofixup entries.

bfd/ChangeLog
bfd/elf32-frv.c

index 0e7dadc35cbe4cc5eb04a8acd21aa2b4d1ac76d5..ecbeaba7c7b83e51788bf4e6c0e06110384cb194 100644 (file)
@@ -1,3 +1,22 @@
+2004-03-02  Alexandre Oliva  <aoliva@redhat.com>
+
+       * elf32-frv.c (struct frv_pic_relocs_info): Added fixups and
+       dynrelocs.
+       (_frv_count_got_plt_entries): Initialize them.
+       (frv_pic_relocs_info_find): Add insert argument.  Adjust all
+       callers.
+       (frv_pic_relocs_info_for_global): Likewise.
+       (frv_pic_relocs_info_for_local): Likewise.
+       (frv_pic_merge_early_relocs_info): New.
+       (_frv_resolve_final_relocs_info): Use it in case one entry maps to
+       another.
+       (_frv_add_dyn_reloc): Add entry argument.  Adjust all callers.
+       Check that we don't exceed the allocated count for entry.
+       (_frv_add_rofixup): Likewise.
+       (_frv_emit_got_relocs_plt_entries): Adjust for coding standards.
+       (elf32_frv_finish_dynamic_sections): Improve error message in case
+       we emit too few rofixup entries.
+
 2004-03-01  Richard Sandiford  <rsandifo@redhat.com>
 
        * archures.c (bfd_mach_fr450): New.
index 4a84addb655169acf2a9ee77b76fa298d40e2e83..de7a1132160cfdd7e6a8d583f61879d67cee28a4 100644 (file)
@@ -748,6 +748,10 @@ struct frv_pic_relocs_info
      relocations referencing the symbol.  */
   unsigned relocs32, relocsfd, relocsfdv;
 
+  /* The number of .rofixups entries and dynamic relocations allocated
+     for this symbol, minus any that might have already been used.  */
+  unsigned fixups, dynrelocs;
+
   /* The offsets of the GOT entries assigned to symbol+addend, to the
      function descriptor's address, and to a function descriptor,
      respectively.  Should be zero if unassigned.  The offsets are
@@ -789,10 +793,14 @@ frv_pic_relocs_info_eq (const void *entry1, const void *entry2)
 static struct frv_pic_relocs_info *
 frv_pic_relocs_info_find (struct htab *ht,
                          bfd *abfd,
-                         const struct frv_pic_relocs_info *entry)
+                         const struct frv_pic_relocs_info *entry,
+                         enum insert_option insert)
 {
   struct frv_pic_relocs_info **loc =
-    (struct frv_pic_relocs_info **) htab_find_slot (ht, entry, INSERT);
+    (struct frv_pic_relocs_info **) htab_find_slot (ht, entry, insert);
+
+  if (! loc)
+    return NULL;
 
   if (*loc)
     return *loc;
@@ -818,7 +826,8 @@ inline static struct frv_pic_relocs_info *
 frv_pic_relocs_info_for_global (struct htab *ht,
                                bfd *abfd,
                                struct elf_link_hash_entry *h,
-                               bfd_vma addend)
+                               bfd_vma addend,
+                               enum insert_option insert)
 {
   struct frv_pic_relocs_info entry;
 
@@ -826,7 +835,7 @@ frv_pic_relocs_info_for_global (struct htab *ht,
   entry.d.h = h;
   entry.addend = addend;
 
-  return frv_pic_relocs_info_find (ht, abfd, &entry);
+  return frv_pic_relocs_info_find (ht, abfd, &entry, insert);
 }
 
 /* Obtain the address of the entry in HT associated with the SYMNDXth
@@ -836,7 +845,8 @@ inline static struct frv_pic_relocs_info *
 frv_pic_relocs_info_for_local (struct htab *ht,
                               bfd *abfd,
                               long symndx,
-                              bfd_vma addend)
+                              bfd_vma addend,
+                              enum insert_option insert)
 {
   struct frv_pic_relocs_info entry;
 
@@ -844,7 +854,59 @@ frv_pic_relocs_info_for_local (struct htab *ht,
   entry.d.abfd = abfd;
   entry.addend = addend;
 
-  return frv_pic_relocs_info_find (ht, abfd, &entry);
+  return frv_pic_relocs_info_find (ht, abfd, &entry, insert);
+}
+
+/* Merge fields set by check_relocs() of two entries that end up being
+   mapped to the same (presumably global) symbol.  */
+
+inline static void
+frv_pic_merge_early_relocs_info (struct frv_pic_relocs_info *e2,
+                                struct frv_pic_relocs_info const *e1)
+{
+  e2->got12 |= e1->got12;
+  e2->gotlos |= e1->gotlos;
+  e2->gothilo |= e1->gothilo;
+  e2->fd |= e1->fd;
+  e2->fdgot12 |= e1->fdgot12;
+  e2->fdgotlos |= e1->fdgotlos;
+  e2->fdgothilo |= e1->fdgothilo;
+  e2->fdgoff12 |= e1->fdgoff12;
+  e2->fdgofflos |= e1->fdgofflos;
+  e2->fdgoffhilo |= e1->fdgoffhilo;
+  e2->gotoff |= e1->gotoff;
+  e2->call |= e1->call;
+  e2->sym |= e1->sym;
+
+#if 0
+  /* These are set in _frv_count_got_plt_entries() or later, and this
+     function is only called in _frv_resolve_final_relocs_info(), that
+     runs just before it, so we don't have to worry about the fields
+     below.  */
+
+  e2->plt |= e1->plt;
+  e2->privfd |= e1->privfd;
+  e2->lazyplt |= e1->lazyplt;
+  e2->done |= e1->done;
+
+  e2->relocs32 += e1->relocs32;
+  e2->relocsfd += e1->relocsfd;
+  e2->relocsfdv += e1->relocsfdv;
+  e2->fixups += e1->fixups;
+  e2->dynrelocs += e1->dynrelocs;
+
+  if (abs (e1->got_entry) < abs (e2->got_entry))
+    e2->got_entry = e1->got_entry;
+  if (abs (e1->fdgot_entry) < abs (e2->fdgot_entry))
+    e2->fdgot_entry = e1->fdgot_entry;
+  if (abs (e1->fd_entry) < abs (e2->fd_entry))
+    e2->fd_entry = e1->fd_entry;
+
+  if (e1->plt_entry < e2->plt_entry)
+    e2->plt_entry = e1->plt_entry;
+  if (e1->lzplt_entry < e2->lzplt_entry)
+    e2->lzplt_entry = e1->lzplt_entry;
+#endif
 }
 
 /* Every block of 65535 lazy PLT entries shares a single call to the
@@ -859,7 +921,8 @@ frv_pic_relocs_info_for_local (struct htab *ht,
 
 inline static bfd_vma
 _frv_add_dyn_reloc (bfd *output_bfd, asection *sreloc, bfd_vma offset,
-                   int reloc_type, long dynindx, bfd_vma addend)
+                   int reloc_type, long dynindx, bfd_vma addend,
+                   struct frv_pic_relocs_info *entry)
 {
   Elf_Internal_Rela outrel;
   bfd_vma reloc_offset;
@@ -874,13 +937,17 @@ _frv_add_dyn_reloc (bfd *output_bfd, asection *sreloc, bfd_vma offset,
                            sreloc->contents + reloc_offset);
   sreloc->reloc_count++;
 
+  BFD_ASSERT (entry->dynrelocs > 0);
+  entry->dynrelocs--;
+
   return reloc_offset;
 }
 
 /* Add a fixup to the ROFIXUP section.  */
 
 static bfd_vma
-_frv_add_rofixup (bfd *output_bfd, asection *rofixup, bfd_vma offset)
+_frv_add_rofixup (bfd *output_bfd, asection *rofixup, bfd_vma offset,
+                 struct frv_pic_relocs_info *entry)
 {
   bfd_vma fixup_offset;
 
@@ -894,7 +961,13 @@ _frv_add_rofixup (bfd *output_bfd, asection *rofixup, bfd_vma offset)
       bfd_put_32 (output_bfd, offset, rofixup->contents + fixup_offset);
     }
   rofixup->reloc_count++;
-             
+
+  if (entry)
+    {
+      BFD_ASSERT (entry->fixups > 0);
+      entry->fixups--;
+    }
+
   return fixup_offset;
 }
 
@@ -999,13 +1072,13 @@ _frv_emit_got_relocs_plt_entries (struct frv_pic_relocs_info *entry,
        {
          if (sec)
            ad += sec->output_section->vma;
-         if (entry->symndx != -1 ||
-             entry->d.h->root.type != bfd_link_hash_undefweak)
+         if (entry->symndx != -1
+             || entry->d.h->root.type != bfd_link_hash_undefweak)
            _frv_add_rofixup (output_bfd, frv_gotfixup_section (info),
                              frv_got_section (info)->output_section->vma
                              + frv_got_section (info)->output_offset
                              + frv_got_initial_offset (info)
-                             + entry->got_entry);
+                             + entry->got_entry, entry);
        }
       else
        _frv_add_dyn_reloc (output_bfd, frv_gotrel_section (info),
@@ -1016,7 +1089,7 @@ _frv_emit_got_relocs_plt_entries (struct frv_pic_relocs_info *entry,
                             + entry->got_entry)
                            + frv_got_section (info)->output_section->vma
                            + frv_got_section (info)->output_offset,
-                           R_FRV_32, idx, ad);
+                           R_FRV_32, idx, ad, entry);
        
       bfd_put_32 (output_bfd, ad,
                  frv_got_section (info)->contents
@@ -1089,7 +1162,7 @@ _frv_emit_got_relocs_plt_entries (struct frv_pic_relocs_info *entry,
                                frv_got_section (info)->output_section->vma
                                + frv_got_section (info)->output_offset
                                + frv_got_initial_offset (info)
-                               + entry->fdgot_entry);
+                               + entry->fdgot_entry, entry);
            }
          else
            _frv_add_dyn_reloc (output_bfd, frv_gotrel_section (info),
@@ -1100,7 +1173,7 @@ _frv_emit_got_relocs_plt_entries (struct frv_pic_relocs_info *entry,
                                 + entry->fdgot_entry)
                                + frv_got_section (info)->output_section->vma
                                + frv_got_section (info)->output_offset,
-                               reloc, idx, ad);
+                               reloc, idx, ad, entry);
        }
 
       bfd_put_32 (output_bfd, ad,
@@ -1142,19 +1215,19 @@ _frv_emit_got_relocs_plt_entries (struct frv_pic_relocs_info *entry,
          if (sec)
            ad += sec->output_section->vma;
          ofst = 0;
-         if (entry->symndx != -1 ||
-             entry->d.h->root.type != bfd_link_hash_undefweak)
+         if (entry->symndx != -1
+             || entry->d.h->root.type != bfd_link_hash_undefweak)
            {
              _frv_add_rofixup (output_bfd, frv_gotfixup_section (info),
                                frv_got_section (info)->output_section->vma
                                + frv_got_section (info)->output_offset
                                + frv_got_initial_offset (info)
-                               + entry->fd_entry);
+                               + entry->fd_entry, entry);
              _frv_add_rofixup (output_bfd, frv_gotfixup_section (info),
                                frv_got_section (info)->output_section->vma
                                + frv_got_section (info)->output_offset
                                + frv_got_initial_offset (info)
-                               + entry->fd_entry + 4);
+                               + entry->fd_entry + 4, entry);
            }
        }
       else
@@ -1170,7 +1243,7 @@ _frv_emit_got_relocs_plt_entries (struct frv_pic_relocs_info *entry,
                                 + entry->fd_entry)
                                + frv_got_section (info)->output_section->vma
                                + frv_got_section (info)->output_offset,
-                               R_FRV_FUNCDESC_VALUE, idx, ad);
+                               R_FRV_FUNCDESC_VALUE, idx, ad, entry);
        }
 
       /* If we've omitted the dynamic relocation, just emit the fixed
@@ -1922,14 +1995,14 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
          if (h != NULL)
            picrel = frv_pic_relocs_info_for_global (frv_relocs_info (info),
                                                     input_bfd, h,
-                                                    orig_addend);
+                                                    orig_addend, INSERT);
          else
            /* In order to find the entry we created before, we must
               use the original addend, not the one that may have been
               modified by _bfd_elf_rela_local_sym().  */
            picrel = frv_pic_relocs_info_for_local (frv_relocs_info (info),
                                                    input_bfd, r_symndx,
-                                                   orig_addend);
+                                                   orig_addend, INSERT);
          if (! picrel)
            return FALSE;
 
@@ -2092,7 +2165,8 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
                                          (output_bfd, info,
                                           input_section, rel->r_offset)
                                          + input_section->output_section->vma
-                                         + input_section->output_offset);
+                                         + input_section->output_offset,
+                                         picrel);
                      }
                  }
                else if ((bfd_get_section_flags (output_bfd,
@@ -2114,7 +2188,7 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
                                         input_section, rel->r_offset)
                                        + input_section->output_section->vma
                                        + input_section->output_offset,
-                                       r_type, dynindx, addend);
+                                       r_type, dynindx, addend, picrel);
                  }
              }
 
@@ -2192,7 +2266,8 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
                                          (output_bfd, info,
                                           input_section, rel->r_offset)
                                          + input_section->output_section->vma
-                                         + input_section->output_offset);
+                                         + input_section->output_offset,
+                                         picrel);
                        if (r_type == R_FRV_FUNCDESC_VALUE)
                          _frv_add_rofixup
                            (output_bfd,
@@ -2201,7 +2276,7 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
                             (output_bfd, info,
                              input_section, rel->r_offset)
                             + input_section->output_section->vma
-                            + input_section->output_offset + 4);
+                            + input_section->output_offset + 4, picrel);
                      }
                  }
              }
@@ -2226,7 +2301,7 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
                                         input_section, rel->r_offset)
                                        + input_section->output_section->vma
                                        + input_section->output_offset,
-                                       r_type, dynindx, addend);
+                                       r_type, dynindx, addend, picrel);
                  }
                /* We want the addend in-place because dynamic
                   relocations are REL.  Setting relocation to it
@@ -2806,6 +2881,7 @@ _frv_count_got_plt_entries (void **entryp, void *dinfo_)
 {
   struct frv_pic_relocs_info *entry = *entryp;
   struct _frv_dynamic_got_info *dinfo = dinfo_;
+  unsigned relocs = 0, fixups = 0;
 
   /* Allocate space for a GOT entry pointing to the symbol.  */
   if (entry->got12)
@@ -2862,27 +2938,33 @@ _frv_count_got_plt_entries (void **entryp, void *dinfo_)
     dinfo->lzplt += 8;
 
   if (!dinfo->info->executable || dinfo->info->pie)
-    dinfo->relocs += entry->relocs32 + entry->relocsfd + entry->relocsfdv;
+    relocs = entry->relocs32 + entry->relocsfd + entry->relocsfdv;
   else
     {
       if (entry->symndx != -1 || FRV_SYM_LOCAL (dinfo->info, entry->d.h))
        {
          if (entry->symndx != -1
-             || entry->d.h->root.type != bfd_link_hash_undefweak)        
-           dinfo->fixups += entry->relocs32 + 2 * entry->relocsfdv;
+             || entry->d.h->root.type != bfd_link_hash_undefweak)
+           fixups += entry->relocs32 + 2 * entry->relocsfdv;
        }
       else
-       dinfo->relocs += entry->relocs32 + entry->relocsfdv;
+       relocs += entry->relocs32 + entry->relocsfdv;
+
       if (entry->symndx != -1 || FRV_FUNCDESC_LOCAL (dinfo->info, entry->d.h))
        {
          if (entry->symndx != -1
              || entry->d.h->root.type != bfd_link_hash_undefweak)
-           dinfo->fixups += entry->relocsfd;
+           fixups += entry->relocsfd;
        }
       else
-       dinfo->relocs += entry->relocsfd;
+       relocs += entry->relocsfd;
     }
 
+  entry->dynrelocs += relocs;
+  entry->fixups += fixups;
+  dinfo->relocs += relocs;
+  dinfo->fixups += fixups;
+
   return 1;
 }
 
@@ -3210,6 +3292,7 @@ _frv_resolve_final_relocs_info (void **entryp, void *p)
   if (entry->symndx == -1)
     {
       struct elf_link_hash_entry *h = entry->d.h;
+      struct frv_pic_relocs_info *oentry;
 
       while (h->root.type == bfd_link_hash_indirect
             || h->root.type == bfd_link_hash_warning)
@@ -3218,6 +3301,17 @@ _frv_resolve_final_relocs_info (void **entryp, void *p)
       if (entry->d.h == h)
        return 1;
 
+      oentry = frv_pic_relocs_info_for_global (*htab, 0, h, entry->addend,
+                                              NO_INSERT);
+
+      if (oentry)
+       {
+         /* Merge the two entries.  */
+         frv_pic_merge_early_relocs_info (oentry, entry);
+         htab_clear_slot (*htab, entryp);
+         return 1;
+       }
+
       entry->d.h = h;
 
       /* If we can't find this entry with the new bfd hash, re-insert
@@ -3581,13 +3675,22 @@ elf32_frv_finish_dynamic_sections (bfd *output_bfd,
                + hgot->root.u.def.section->output_offset;
 
              _frv_add_rofixup (output_bfd, frv_gotfixup_section (info),
-                               got_value);
+                               got_value, 0);
            }
 
          if (frv_gotfixup_section (info)->_raw_size
              != (frv_gotfixup_section (info)->reloc_count * 4))
            {
-             if (!elf_hash_table (info)->dynamic_sections_created)
+             if (frv_gotfixup_section (info)->_raw_size
+                 < frv_gotfixup_section (info)->reloc_count * 4)
+               {
+                 info->callbacks->warning
+                   (info, "LINKER BUG: .rofixup section size mismatch",
+                    ".rofixup", NULL, NULL, 0);
+                 abort ();
+                 return FALSE;
+               }
+             else if (!elf_hash_table (info)->dynamic_sections_created)
                {
                  info->callbacks->warning
                    (info, "no dynamic sections, missing -melf32frvfd?",
@@ -3931,12 +4034,12 @@ elf32_frv_check_relocs (abfd, info, sec, relocs)
              picrel
                = frv_pic_relocs_info_for_global (frv_relocs_info (info),
                                                  abfd, h,
-                                                 rel->r_addend);
+                                                 rel->r_addend, INSERT);
            }
          else
            picrel = frv_pic_relocs_info_for_local (frv_relocs_info (info),
                                                    abfd, r_symndx,
-                                                   rel->r_addend);
+                                                   rel->r_addend, INSERT);
          if (! picrel)
            return FALSE;
          break;
This page took 0.047968 seconds and 4 git commands to generate.