* elfxx-mips.c (mips_elf_set_global_got_offset): Don't set no_fn_stub.
authorRichard Sandiford <rdsandiford@googlemail.com>
Wed, 26 Nov 2003 20:58:45 +0000 (20:58 +0000)
committerRichard Sandiford <rdsandiford@googlemail.com>
Wed, 26 Nov 2003 20:58:45 +0000 (20:58 +0000)
(mips_elf_set_no_stub): New function.
(mips_elf_multi_got): Call it.
(_bfd_mips_elf_finish_dynamic_symbol): If a relocation is needed for
a secondary GOT entry, create an R_MIPS_32 or R_MIPS_64 relocation and
use mips_elf_create_dynamic_relocation to deal with any compatibility
issues.  Store the adjusted addend in the GOT slot.

bfd/ChangeLog
bfd/elfxx-mips.c

index 562126f..950890c 100644 (file)
@@ -1,3 +1,14 @@
+2003-11-26  Daniel Jacobowitz  <drow@mvista.com>
+            Richard Sandiford  <rsandifo@redhat.com>
+
+       * elfxx-mips.c (mips_elf_set_global_got_offset): Don't set no_fn_stub.
+       (mips_elf_set_no_stub): New function.
+       (mips_elf_multi_got): Call it.
+       (_bfd_mips_elf_finish_dynamic_symbol): If a relocation is needed for
+       a secondary GOT entry, create an R_MIPS_32 or R_MIPS_64 relocation and
+       use mips_elf_create_dynamic_relocation to deal with any compatibility
+       issues.  Store the adjusted addend in the GOT slot.
+
 2003-11-25  Mattias EngdegĂ„rd  <mattias@virtutech.se>
 
        * stabs.c (_bfd_link_section_stabs): Skip N_EXCL stabs when
index b7224a5..0c94909 100644 (file)
@@ -471,6 +471,7 @@ static int mips_elf_bfd2got_entry_eq PARAMS ((const PTR, const PTR));
 static int mips_elf_make_got_per_bfd PARAMS ((void **, void *));
 static int mips_elf_merge_gots PARAMS ((void **, void *));
 static int mips_elf_set_global_got_offset PARAMS ((void**, void *));
+static int mips_elf_set_no_stub PARAMS ((void **, void *));
 static int mips_elf_resolve_final_got_entry PARAMS ((void**, void *));
 static void mips_elf_resolve_final_got_entries
   PARAMS ((struct mips_got_info *));
@@ -2338,10 +2339,6 @@ mips_elf_set_global_got_offset (entryp, p)
          BFD_ASSERT (g->global_gotsym == NULL);
 
          entry->gotidx = arg->value * (long) g->assigned_gotno++;
-         /* We can't do lazy update of GOT entries for
-            non-primary GOTs since the PLT entries don't use the
-            right offsets, so punt at it for now.  */
-         entry->d.h->no_fn_stub = TRUE;
          if (arg->info->shared
              || (elf_hash_table (arg->info)->dynamic_sections_created
                  && ((entry->d.h->root.elf_link_hash_flags
@@ -2357,6 +2354,23 @@ mips_elf_set_global_got_offset (entryp, p)
   return 1;
 }
 
+/* Mark any global symbols referenced in the GOT we are iterating over
+   as inelligible for lazy resolution stubs.  */
+static int
+mips_elf_set_no_stub (entryp, p)
+     void **entryp;
+     void *p ATTRIBUTE_UNUSED;
+{
+  struct mips_got_entry *entry = (struct mips_got_entry *)*entryp;
+
+  if (entry->abfd != NULL
+      && entry->symndx == -1
+      && entry->d.h->root.dynindx != -1)
+    entry->d.h->no_fn_stub = TRUE;
+
+  return 1;
+}
+
 /* Follow indirect and warning hash entries so that each got entry
    points to the final symbol definition.  P must point to a pointer
    to the hash table we're traversing.  Since this traversal may
@@ -2624,6 +2638,11 @@ mips_elf_multi_got (abfd, info, g, got, pages)
       g->next = gg->next;
       gg->next = g;
       g = gn;
+
+      /* Mark global symbols in every non-primary GOT as ineligible for
+        stubs.  */
+      if (g)
+       htab_traverse (g->got_entries, mips_elf_set_no_stub, NULL);
     }
   while (g);
 
@@ -6660,10 +6679,8 @@ _bfd_mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
   if (g->next && h->dynindx != -1)
     {
       struct mips_got_entry e, *p;
+      bfd_vma entry;
       bfd_vma offset;
-      bfd_vma value;
-      Elf_Internal_Rela rel[3];
-      bfd_vma addend = 0;
 
       gg = g;
 
@@ -6671,18 +6688,6 @@ _bfd_mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
       e.symndx = -1;
       e.d.h = (struct mips_elf_link_hash_entry *)h;
 
-      if (info->shared
-         || h->root.type == bfd_link_hash_undefined
-         || h->root.type == bfd_link_hash_undefweak)
-       value = 0;
-      else if (sym->st_value)
-       value = sym->st_value;
-      else
-       value = h->root.u.def.value;
-
-      memset (rel, 0, sizeof (rel));
-      rel[0].r_info = ELF_R_INFO (output_bfd, 0, R_MIPS_REL32);
-
       for (g = g->next; g->next != gg; g = g->next)
        {
          if (g->got_entries
@@ -6690,22 +6695,37 @@ _bfd_mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
                                                           &e)))
            {
              offset = p->gotidx;
-             rel[0].r_offset = rel[1].r_offset = rel[2].r_offset = offset;
-
-             MIPS_ELF_PUT_WORD (output_bfd, value, sgot->contents + offset);
-
-             if ((info->shared
-                  || (elf_hash_table (info)->dynamic_sections_created
-                      && p->d.h != NULL
-                      && ((p->d.h->root.elf_link_hash_flags
-                           & ELF_LINK_HASH_DEF_DYNAMIC) != 0)
-                      && ((p->d.h->root.elf_link_hash_flags
-                           & ELF_LINK_HASH_DEF_REGULAR) == 0)))
-                 && ! (mips_elf_create_dynamic_relocation
-                       (output_bfd, info, rel,
-                        e.d.h, NULL, value, &addend, sgot)))
-               return FALSE;
-             BFD_ASSERT (addend == 0);
+             if (info->shared
+                 || (elf_hash_table (info)->dynamic_sections_created
+                     && p->d.h != NULL
+                     && ((p->d.h->root.elf_link_hash_flags
+                          & ELF_LINK_HASH_DEF_DYNAMIC) != 0)
+                     && ((p->d.h->root.elf_link_hash_flags
+                          & ELF_LINK_HASH_DEF_REGULAR) == 0)))
+               {
+                 /* Create an R_MIPS_REL32 relocation for this entry.  Due to
+                    the various compatibility problems, it's easier to mock
+                    up an R_MIPS_32 or R_MIPS_64 relocation and leave
+                    mips_elf_create_dynamic_relocation to calculate the
+                    appropriate addend.  */
+                 Elf_Internal_Rela rel[3];
+
+                 memset (rel, 0, sizeof (rel));
+                 if (ABI_64_P (output_bfd))
+                   rel[0].r_info = ELF_R_INFO (output_bfd, 0, R_MIPS_64);
+                 else
+                   rel[0].r_info = ELF_R_INFO (output_bfd, 0, R_MIPS_32);
+                 rel[0].r_offset = rel[1].r_offset = rel[2].r_offset = offset;
+
+                 entry = 0;
+                 if (! (mips_elf_create_dynamic_relocation
+                        (output_bfd, info, rel,
+                         e.d.h, NULL, sym->st_value, &entry, sgot)))
+                   return FALSE;
+               }
+             else
+               entry = sym->st_value;
+             MIPS_ELF_PUT_WORD (output_bfd, entry, sgot->contents + offset);
            }
        }
     }