bfd/
authorRichard Sandiford <rdsandiford@googlemail.com>
Thu, 7 Aug 2008 19:57:28 +0000 (19:57 +0000)
committerRichard Sandiford <rdsandiford@googlemail.com>
Thu, 7 Aug 2008 19:57:28 +0000 (19:57 +0000)
* elf32-mips.c (elf_backend_hide_symbol): Delete.
* elfn32-mips.c (elf_backend_hide_symbol): Likewise.
* elf64-mips.c (elf_backend_hide_symbol): Likewise.
* elfxx-mips.h (elf_backend_hide_symbol): Likewise.
* elfxx-mips.c (mips_elf_link_hash_entry): Remove "forced_local"
and add "needs_lazy_stub".
(mips_elf_link_hash_newfunc): Update accordingly.
(mips_elf_link_hash_table): Remove "computed_got_sizes" and
add "lazy_stub_count".
(_bfd_mips_elf_link_hash_table_create): Update accordingly.
(mips_elf_output_extsym): Use hd->needs_lazy_stub to detect
cases where a lazy stub is being used.
(mips_elf_sort_hash_table_f): Use h->root.forced_local instead
of h->forced_local.
(mips_elf_record_global_got_symbol): Use _bfd_elf_link_hash_hide_symbol
instead of _bfd_mips_elf_hide_symbol.  Do not increment local_gotno
here.
(mips_elf_allocate_dynamic_relocations): Move before new first use.
(mips_elf_check_recreate_got, mips_elf_recreate_got): New functions.
(mips_elf_resolve_final_got_entries): Move earlier in file.  Make at
most two passes over the hash table.  Use mips_elf_check_recreate_got
to see if there are any indirect or warning entries and
mips_elf_recreate_got to create a new GOT without them.
Return a boolean success value.
(mips_elf_count_forced_local_got_entries): New function.
(mips_elf_make_got_per_bfd): Check h->root.forced_local instead of
h->forced_local.
(mips_elf_set_global_got_offset): Likewise.
(mips_elf_set_no_stub): Replace with...
(mips_elf_forbid_lazy_stubs): ...this new function.
(mips_elf_resolve_final_got_entry): Delete.
(mips_elf_multi_got): Fix formatting.  Use mips_elf_forbid_lazy_stubs
instead of mips_elf_set_no_stub.  Move the code that sets
global offsets and allocates dynamic relocations from the main
_bfd_mips_elf_size_dynamic_sections loop to here.
(_bfd_mips_elf_adjust_dynamic_symbol): Do not allocate room in
.MIPS.stubs here; just set hmips->needs_lazy_stub and increment
htab->lazy_stub_count.
(_bfd_mips_elf_always_size_sections): Move the stub-estimation
code to mips_elf_estimate_stub_size and the GOT-sizing code to
mips_elf_lay_out_got.  Do not call these functions here.
(mips_elf_estimate_stub_size): New function, split
out from _bfd_mips_elf_always_size_sections.  Call
mips_elf_resolve_final_got_entries earlier.  Count the number
of forced-local entries.  Do not add stub sizes to loadable_size;
after this patch, the stub sizes are already included in the main
estimate.  Allocate dynamic relocations here rather than in the
main _bfd_mips_elf_size_dynamic_sections loop.
(mips_elf_estimate_stub_size): New function, split out from
_bfd_mips_elf_always_size_sections.
(mips_elf_allocate_lazy_stub): New function.
(mips_elf_lay_out_lazy_stubs): Likewise.
(_bfd_mips_elf_size_dynamic_sections): Call mips_elf_estimate_stub_size,
mips_elf_lay_out_got and mips_elf_lay_out_lazy_stubs.  Do not handle
the allocation of sreldyn specially.
(_bfd_mips_elf_hide_symbol): Delete.

ld/testsuite/
* ld-mips-elf/tlsdyn-o32-2.got, ld-mips-elf/tlsdyn-o32-3.got,
ld-mips-elf/tlsdyn-o32-2.d, ld-mips-elf/tlsdyn-o32-3.d: Change the
GOT layout as follows:

         BEFORE                  AFTER
   +0x08 %call16(__tls_get_addr) %call16(__tls_get_addr)
   +0x0c %tlsldm(tlsbin_ld)      %gottprel(tlsvar_ie)
   +0x10   "  "                  %tlsgd(tlsvar_gd)
   +0x14 %tlsgd(tlsvar_gd)          "  "
   +0x18   "  "                  %tlsgd(tlsbin_gd)
   +0x1c %gottprel(tlsvar_ie)       "  "
   +0x20 %tlsgd(tlsbin_gd)       %tlsldm(tlsbin_ld)
   +0x24   "  "                     "  "
   +0x28 %gottprel(tlsbin_ie)    %gottprel(tlsbin_ie)

bfd/ChangeLog
bfd/elf32-mips.c
bfd/elf64-mips.c
bfd/elfn32-mips.c
bfd/elfxx-mips.c
bfd/elfxx-mips.h
ld/testsuite/ChangeLog
ld/testsuite/ld-mips-elf/tlsdyn-o32-2.d
ld/testsuite/ld-mips-elf/tlsdyn-o32-2.got
ld/testsuite/ld-mips-elf/tlsdyn-o32-3.d
ld/testsuite/ld-mips-elf/tlsdyn-o32-3.got

index 40a5085..ee151a7 100644 (file)
@@ -1,5 +1,64 @@
 2008-08-07  Richard Sandiford  <rdsandiford@googlemail.com>
 
+       * elf32-mips.c (elf_backend_hide_symbol): Delete.
+       * elfn32-mips.c (elf_backend_hide_symbol): Likewise.
+       * elf64-mips.c (elf_backend_hide_symbol): Likewise.
+       * elfxx-mips.h (elf_backend_hide_symbol): Likewise.
+       * elfxx-mips.c (mips_elf_link_hash_entry): Remove "forced_local"
+       and add "needs_lazy_stub".
+       (mips_elf_link_hash_newfunc): Update accordingly.
+       (mips_elf_link_hash_table): Remove "computed_got_sizes" and
+       add "lazy_stub_count".
+       (_bfd_mips_elf_link_hash_table_create): Update accordingly.
+       (mips_elf_output_extsym): Use hd->needs_lazy_stub to detect
+       cases where a lazy stub is being used.
+       (mips_elf_sort_hash_table_f): Use h->root.forced_local instead
+       of h->forced_local.
+       (mips_elf_record_global_got_symbol): Use _bfd_elf_link_hash_hide_symbol
+       instead of _bfd_mips_elf_hide_symbol.  Do not increment local_gotno
+       here.
+       (mips_elf_allocate_dynamic_relocations): Move before new first use.
+       (mips_elf_check_recreate_got, mips_elf_recreate_got): New functions.
+       (mips_elf_resolve_final_got_entries): Move earlier in file.  Make at
+       most two passes over the hash table.  Use mips_elf_check_recreate_got
+       to see if there are any indirect or warning entries and
+       mips_elf_recreate_got to create a new GOT without them.
+       Return a boolean success value.
+       (mips_elf_count_forced_local_got_entries): New function.
+       (mips_elf_make_got_per_bfd): Check h->root.forced_local instead of
+       h->forced_local.
+       (mips_elf_set_global_got_offset): Likewise.
+       (mips_elf_set_no_stub): Replace with...
+       (mips_elf_forbid_lazy_stubs): ...this new function.
+       (mips_elf_resolve_final_got_entry): Delete.
+       (mips_elf_multi_got): Fix formatting.  Use mips_elf_forbid_lazy_stubs
+       instead of mips_elf_set_no_stub.  Move the code that sets
+       global offsets and allocates dynamic relocations from the main
+       _bfd_mips_elf_size_dynamic_sections loop to here.
+       (_bfd_mips_elf_adjust_dynamic_symbol): Do not allocate room in
+       .MIPS.stubs here; just set hmips->needs_lazy_stub and increment
+       htab->lazy_stub_count.
+       (_bfd_mips_elf_always_size_sections): Move the stub-estimation
+       code to mips_elf_estimate_stub_size and the GOT-sizing code to
+       mips_elf_lay_out_got.  Do not call these functions here.
+       (mips_elf_estimate_stub_size): New function, split
+       out from _bfd_mips_elf_always_size_sections.  Call
+       mips_elf_resolve_final_got_entries earlier.  Count the number
+       of forced-local entries.  Do not add stub sizes to loadable_size;
+       after this patch, the stub sizes are already included in the main
+       estimate.  Allocate dynamic relocations here rather than in the
+       main _bfd_mips_elf_size_dynamic_sections loop.
+       (mips_elf_estimate_stub_size): New function, split out from
+       _bfd_mips_elf_always_size_sections.
+       (mips_elf_allocate_lazy_stub): New function.
+       (mips_elf_lay_out_lazy_stubs): Likewise.
+       (_bfd_mips_elf_size_dynamic_sections): Call mips_elf_estimate_stub_size,
+       mips_elf_lay_out_got and mips_elf_lay_out_lazy_stubs.  Do not handle
+       the allocation of sreldyn specially.
+       (_bfd_mips_elf_hide_symbol): Delete.
+
+2008-08-07  Richard Sandiford  <rdsandiford@googlemail.com>
+
        * elfxx-mips.c (allocate_dynrelocs): Ignore indirect and warning
        symbols.
 
index 8169991..526c222 100644 (file)
@@ -1606,7 +1606,6 @@ static const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap = {
 #define elf_backend_gc_sweep_hook      _bfd_mips_elf_gc_sweep_hook
 #define elf_backend_copy_indirect_symbol \
                                        _bfd_mips_elf_copy_indirect_symbol
-#define elf_backend_hide_symbol                _bfd_mips_elf_hide_symbol
 #define elf_backend_grok_prstatus      elf32_mips_grok_prstatus
 #define elf_backend_grok_psinfo                elf32_mips_grok_psinfo
 #define elf_backend_ecoff_debug_swap   &mips_elf32_ecoff_debug_swap
index 520fafe..f79d889 100644 (file)
@@ -3179,7 +3179,6 @@ const struct elf_size_info mips_elf64_size_info =
 #define elf_backend_gc_sweep_hook      _bfd_mips_elf_gc_sweep_hook
 #define elf_backend_copy_indirect_symbol \
                                        _bfd_mips_elf_copy_indirect_symbol
-#define elf_backend_hide_symbol                _bfd_mips_elf_hide_symbol
 #define elf_backend_ignore_discarded_relocs \
                                        _bfd_mips_elf_ignore_discarded_relocs
 #define elf_backend_mips_irix_compat   elf64_mips_irix_compat
index 2a2d59e..63734f8 100644 (file)
@@ -2433,7 +2433,6 @@ static const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap = {
 #define elf_backend_gc_sweep_hook      _bfd_mips_elf_gc_sweep_hook
 #define elf_backend_copy_indirect_symbol \
                                        _bfd_mips_elf_copy_indirect_symbol
-#define elf_backend_hide_symbol                _bfd_mips_elf_hide_symbol
 #define elf_backend_grok_prstatus      elf32_mips_grok_prstatus
 #define elf_backend_grok_psinfo                elf32_mips_grok_psinfo
 #define elf_backend_ecoff_debug_swap   &mips_elf32_ecoff_debug_swap
index f3536fd..e3e07fe 100644 (file)
@@ -317,15 +317,15 @@ struct mips_elf_link_hash_entry
      in any relocs other than a 16 bit call.  */
   unsigned int need_fn_stub : 1;
 
-  /* Are we forced local?  This will only be set if we have converted
-     the initial global GOT entry to a local GOT entry.  */
-  unsigned int forced_local : 1;
-
   /* Are we referenced by some kind of relocation?  */
   unsigned int is_relocation_target : 1;
 
   /* Are we referenced by branch relocations?  */
   unsigned int is_branch_target : 1;
+
+  /* Does this symbol need a traditional MIPS lazy-binding stub
+     (as opposed to a PLT entry)?  */
+  unsigned int needs_lazy_stub : 1;
 };
 
 /* MIPS ELF linker hash table.  */
@@ -349,8 +349,6 @@ struct mips_elf_link_hash_table
   bfd_vma rld_value;
   /* This is set if we see any mips16 stub sections.  */
   bfd_boolean mips16_stubs_seen;
-  /* True if we've computed the size of the GOT.  */
-  bfd_boolean computed_got_sizes;
   /* True if we're generating code for VxWorks.  */
   bfd_boolean is_vxworks;
   /* True if we already reported the small-data section overflow.  */
@@ -371,6 +369,8 @@ struct mips_elf_link_hash_table
   bfd_vma plt_header_size;
   /* The size of a PLT entry in bytes (VxWorks only).  */
   bfd_vma plt_entry_size;
+  /* The number of functions that need a lazy-binding stub.  */
+  bfd_vma lazy_stub_count;
   /* The size of a function stub entry in bytes.  */
   bfd_vma function_stub_size;
 };
@@ -871,9 +871,9 @@ mips_elf_link_hash_newfunc (struct bfd_hash_entry *entry,
       ret->readonly_reloc = FALSE;
       ret->no_fn_stub = FALSE;
       ret->need_fn_stub = FALSE;
-      ret->forced_local = FALSE;
       ret->is_relocation_target = FALSE;
       ret->is_branch_target = FALSE;
+      ret->needs_lazy_stub = FALSE;
     }
 
   return (struct bfd_hash_entry *) ret;
@@ -2066,18 +2066,14 @@ mips_elf_output_extsym (struct mips_elf_link_hash_entry *h, void *data)
       else
        h->esym.asym.value = 0;
     }
-  else if (h->root.needs_plt)
+  else
     {
       struct mips_elf_link_hash_entry *hd = h;
-      bfd_boolean no_fn_stub = h->no_fn_stub;
 
       while (hd->root.root.type == bfd_link_hash_indirect)
-       {
-         hd = (struct mips_elf_link_hash_entry *)h->root.root.u.i.link;
-         no_fn_stub = no_fn_stub || hd->no_fn_stub;
-       }
+       hd = (struct mips_elf_link_hash_entry *)h->root.root.u.i.link;
 
-      if (!no_fn_stub)
+      if (hd->needs_lazy_stub)
        {
          /* Set type and value for a symbol with a function stub.  */
          h->esym.asym.st = stProc;
@@ -2965,7 +2961,7 @@ mips_elf_sort_hash_table_f (struct mips_elf_link_hash_entry *h, void *data)
        hsd->low = (struct elf_link_hash_entry *) h;
       h->root.dynindx = hsd->max_unref_got_dynindx++;
     }
-  else if (h->root.got.offset != 1 || h->forced_local)
+  else if (h->root.got.offset != 1 || h->root.forced_local)
     h->root.dynindx = hsd->max_non_got_dynindx++;
   else
     {
@@ -3001,7 +2997,7 @@ mips_elf_record_global_got_symbol (struct elf_link_hash_entry *h,
        {
        case STV_INTERNAL:
        case STV_HIDDEN:
-         _bfd_mips_elf_hide_symbol (info, h, TRUE);
+         _bfd_elf_link_hash_hide_symbol (info, h, TRUE);
          break;
        }
       if (!bfd_elf_link_record_dynamic_symbol (info, h))
@@ -3042,14 +3038,10 @@ mips_elf_record_global_got_symbol (struct elf_link_hash_entry *h,
     return TRUE;
 
   if (tls_flag == 0)
-    {
-      /* By setting this to a value other than -1, we are indicating that
-        there needs to be a GOT entry for H.  Avoid using zero, as the
-        generic ELF copy_indirect_symbol tests for <= 0.  */
-      h->got.offset = 1;
-      if (h->forced_local)
-       g->local_gotno++;
-    }
+    /* By setting this to a value other than -1, we are indicating that
+       there needs to be a GOT entry for H.  Avoid using zero, as the
+       generic ELF copy_indirect_symbol tests for <= 0.  */
+    h->got.offset = 1;
 
   return TRUE;
 }
@@ -3229,6 +3221,148 @@ mips_elf_record_got_page_entry (struct bfd_link_info *info, bfd *abfd,
 
   return TRUE;
 }
+
+/* Add room for N relocations to the .rel(a).dyn section in ABFD.  */
+
+static void
+mips_elf_allocate_dynamic_relocations (bfd *abfd, struct bfd_link_info *info,
+                                      unsigned int n)
+{
+  asection *s;
+  struct mips_elf_link_hash_table *htab;
+
+  htab = mips_elf_hash_table (info);
+  s = mips_elf_rel_dyn_section (info, FALSE);
+  BFD_ASSERT (s != NULL);
+
+  if (htab->is_vxworks)
+    s->size += n * MIPS_ELF_RELA_SIZE (abfd);
+  else
+    {
+      if (s->size == 0)
+       {
+         /* Make room for a null element.  */
+         s->size += MIPS_ELF_REL_SIZE (abfd);
+         ++s->reloc_count;
+       }
+      s->size += n * MIPS_ELF_REL_SIZE (abfd);
+    }
+}
+\f
+/* A htab_traverse callback for GOT entries.  Set boolean *DATA to true
+   if the GOT entry is for an indirect or warning symbol.  */
+
+static int
+mips_elf_check_recreate_got (void **entryp, void *data)
+{
+  struct mips_got_entry *entry;
+  bfd_boolean *must_recreate;
+
+  entry = (struct mips_got_entry *) *entryp;
+  must_recreate = (bfd_boolean *) data;
+  if (entry->abfd != NULL && entry->symndx == -1)
+    {
+      struct mips_elf_link_hash_entry *h;
+
+      h = entry->d.h;
+      if (h->root.root.type == bfd_link_hash_indirect
+         || h->root.root.type == bfd_link_hash_warning)
+       {
+         *must_recreate = TRUE;
+         return 0;
+       }
+    }
+  return 1;
+}
+
+/* A htab_traverse callback for GOT entries.  Add all entries to
+   hash table *DATA, converting entries for indirect and warning
+   symbols into entries for the target symbol.  Set *DATA to null
+   on error.  */
+
+static int
+mips_elf_recreate_got (void **entryp, void *data)
+{
+  htab_t *new_got;
+  struct mips_got_entry *entry;
+  void **slot;
+
+  new_got = (htab_t *) data;
+  entry = (struct mips_got_entry *) *entryp;
+  if (entry->abfd != NULL && entry->symndx == -1)
+    {
+      struct mips_elf_link_hash_entry *h;
+
+      h = entry->d.h;
+      while (h->root.root.type == bfd_link_hash_indirect
+            || h->root.root.type == bfd_link_hash_warning)
+       h = (struct mips_elf_link_hash_entry *) h->root.root.u.i.link;
+      entry->d.h = h;
+    }
+  slot = htab_find_slot (*new_got, entry, INSERT);
+  if (slot == NULL)
+    {
+      *new_got = NULL;
+      return 0;
+    }
+  if (*slot == NULL)
+    *slot = entry;
+  else
+    free (entry);
+  return 1;
+}
+
+/* If any entries in G->got_entries are for indirect or warning symbols,
+   replace them with entries for the target symbol.  */
+
+static bfd_boolean
+mips_elf_resolve_final_got_entries (struct mips_got_info *g)
+{
+  bfd_boolean must_recreate;
+  htab_t new_got;
+
+  must_recreate = FALSE;
+  htab_traverse (g->got_entries, mips_elf_check_recreate_got, &must_recreate);
+  if (must_recreate)
+    {
+      new_got = htab_create (htab_size (g->got_entries),
+                            mips_elf_got_entry_hash,
+                            mips_elf_got_entry_eq, NULL);
+      htab_traverse (g->got_entries, mips_elf_recreate_got, &new_got);
+      if (new_got == NULL)
+       return FALSE;
+
+      /* Each entry in g->got_entries has either been copied to new_got
+        or freed.  Now delete the hash table itself.  */
+      htab_delete (g->got_entries);
+      g->got_entries = new_got;
+    }
+  return TRUE;
+}
+
+/* An elf_link_hash_traverse callback for which DATA points to a mips_got_info.
+   Add each forced-local GOT symbol to DATA's local_gotno field.  */
+
+static int
+mips_elf_count_forced_local_got_symbols (struct elf_link_hash_entry *h,
+                                        void *data)
+{
+  struct mips_got_info *g;
+
+  g = (struct mips_got_info *) data;
+  if (h->got.offset != MINUS_ONE
+      && (h->forced_local || h->dynindx == -1))
+    {
+      /* We no longer need this entry if it was only used for
+        relocations; those relocations will be against the
+        null or section symbol instead of H.  */
+      if (h->got.offset == 2)
+       h->got.offset = MINUS_ONE;
+      else
+       g->local_gotno++;
+    }
+  return 1;
+}
 \f
 /* Compute the hash value of the bfd in a bfd2got hash entry.  */
 
@@ -3360,7 +3494,7 @@ mips_elf_make_got_per_bfd (void **entryp, void *p)
       if (entry->tls_type & GOT_TLS_IE)
        g->tls_gotno += 1;
     }
-  else if (entry->symndx >= 0 || entry->d.h->forced_local)
+  else if (entry->symndx >= 0 || entry->d.h->root.forced_local)
     ++g->local_gotno;
   else
     ++g->global_gotno;
@@ -3593,7 +3727,7 @@ mips_elf_set_global_got_offset (void **entryp, void *p)
 
   if (entry->abfd != NULL && entry->symndx == -1
       && entry->d.h->root.dynindx != -1
-      && !entry->d.h->forced_local
+      && !entry->d.h->root.forced_local
       && entry->d.h->tls_type == GOT_NORMAL)
     {
       if (g)
@@ -3614,85 +3748,31 @@ mips_elf_set_global_got_offset (void **entryp, void *p)
   return 1;
 }
 
-/* Mark any global symbols referenced in the GOT we are iterating over
-   as inelligible for lazy resolution stubs.  */
+/* A htab_traverse callback for GOT entries for which DATA is the
+   bfd_link_info.  Forbid any global symbols from having traditional
+   lazy-binding stubs.  */
+
 static int
-mips_elf_set_no_stub (void **entryp, void *p ATTRIBUTE_UNUSED)
+mips_elf_forbid_lazy_stubs (void **entryp, void *data)
 {
-  struct mips_got_entry *entry = (struct mips_got_entry *)*entryp;
+  struct bfd_link_info *info;
+  struct mips_elf_link_hash_table *htab;
+  struct mips_got_entry *entry;
 
+  entry = (struct mips_got_entry *) *entryp;
+  info = (struct bfd_link_info *) data;
+  htab = mips_elf_hash_table (info);
   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
-   modify the hash table, we set this pointer to NULL to indicate
-   we've made a potentially-destructive change to the hash table, so
-   the traversal must be restarted.  */
-static int
-mips_elf_resolve_final_got_entry (void **entryp, void *p)
-{
-  struct mips_got_entry *entry = (struct mips_got_entry *)*entryp;
-  htab_t got_entries = *(htab_t *)p;
-
-  if (entry->abfd != NULL && entry->symndx == -1)
+      && entry->d.h->needs_lazy_stub)
     {
-      struct mips_elf_link_hash_entry *h = entry->d.h;
-
-      while (h->root.root.type == bfd_link_hash_indirect
-            || h->root.root.type == bfd_link_hash_warning)
-       h = (struct mips_elf_link_hash_entry *) h->root.root.u.i.link;
-
-      if (entry->d.h == h)
-       return 1;
-
-      entry->d.h = h;
-
-      /* If we can't find this entry with the new bfd hash, re-insert
-        it, and get the traversal restarted.  */
-      if (! htab_find (got_entries, entry))
-       {
-         htab_clear_slot (got_entries, entryp);
-         entryp = htab_find_slot (got_entries, entry, INSERT);
-         if (! *entryp)
-           *entryp = entry;
-         /* Abort the traversal, since the whole table may have
-            moved, and leave it up to the parent to restart the
-            process.  */
-         *(htab_t *)p = NULL;
-         return 0;
-       }
-      /* We might want to decrement the global_gotno count, but it's
-        either too early or too late for that at this point.  */
+      entry->d.h->needs_lazy_stub = FALSE;
+      htab->lazy_stub_count--;
     }
 
   return 1;
 }
 
-/* Turn indirect got entries in a got_entries table into their final
-   locations.  */
-static void
-mips_elf_resolve_final_got_entries (struct mips_got_info *g)
-{
-  htab_t got_entries;
-
-  do
-    {
-      got_entries = g->got_entries;
-
-      htab_traverse (got_entries,
-                    mips_elf_resolve_final_got_entry,
-                    &got_entries);
-    }
-  while (got_entries == NULL);
-}
-
 /* Return the offset of an input bfd IBFD's GOT from the beginning of
    the primary GOT.  */
 static bfd_vma
@@ -3724,8 +3804,10 @@ mips_elf_multi_got (bfd *abfd, struct bfd_link_info *info,
   struct mips_elf_got_per_bfd_arg got_per_bfd_arg;
   struct mips_elf_set_global_got_offset_arg set_got_offset_arg;
   struct mips_got_info *g, *gg;
-  unsigned int assign;
+  unsigned int assign, needed_relocs;
+  bfd *dynobj;
 
+  dynobj = elf_hash_table (info)->dynobj;
   htab = mips_elf_hash_table (info);
   g = htab->got_info;
   g->bfd2got = htab_try_create (1, mips_elf_bfd2got_entry_hash,
@@ -3916,16 +3998,49 @@ mips_elf_multi_got (bfd *abfd, struct bfd_link_info *info,
       /* Move onto the next GOT.  It will be a secondary GOT if nonull.  */
       g = gn;
 
-      /* Mark global symbols in every non-primary GOT as ineligible for
-        stubs.  */
+      /* Forbid global symbols in every non-primary GOT from having
+        lazy-binding stubs.  */
       if (g)
-       htab_traverse (g->got_entries, mips_elf_set_no_stub, NULL);
+       htab_traverse (g->got_entries, mips_elf_forbid_lazy_stubs, info);
     }
   while (g);
 
   got->size = (gg->next->local_gotno
-                   + gg->next->global_gotno
-                   + gg->next->tls_gotno) * MIPS_ELF_GOT_SIZE (abfd);
+              + gg->next->global_gotno
+              + gg->next->tls_gotno) * MIPS_ELF_GOT_SIZE (abfd);
+
+  needed_relocs = 0;
+  set_got_offset_arg.value = MIPS_ELF_GOT_SIZE (abfd);
+  set_got_offset_arg.info = info;
+  for (g = gg->next; g && g->next != gg; g = g->next)
+    {
+      unsigned int save_assign;
+
+      /* Assign offsets to global GOT entries.  */
+      save_assign = g->assigned_gotno;
+      g->assigned_gotno = g->local_gotno;
+      set_got_offset_arg.g = g;
+      set_got_offset_arg.needed_relocs = 0;
+      htab_traverse (g->got_entries,
+                    mips_elf_set_global_got_offset,
+                    &set_got_offset_arg);
+      needed_relocs += set_got_offset_arg.needed_relocs;
+      BFD_ASSERT (g->assigned_gotno - g->local_gotno <= g->global_gotno);
+
+      g->assigned_gotno = save_assign;
+      if (info->shared)
+       {
+         needed_relocs += g->local_gotno - g->assigned_gotno;
+         BFD_ASSERT (g->assigned_gotno == g->next->local_gotno
+                     + g->next->global_gotno
+                     + g->next->tls_gotno
+                     + MIPS_RESERVED_GOTNO (info));
+       }
+    }
+
+  if (needed_relocs)
+    mips_elf_allocate_dynamic_relocations (dynobj, info,
+                                          needed_relocs);
 
   return TRUE;
 }
@@ -5059,33 +5174,6 @@ mips_elf_perform_relocation (struct bfd_link_info *info,
   return TRUE;
 }
 \f
-/* Add room for N relocations to the .rel(a).dyn section in ABFD.  */
-
-static void
-mips_elf_allocate_dynamic_relocations (bfd *abfd, struct bfd_link_info *info,
-                                      unsigned int n)
-{
-  asection *s;
-  struct mips_elf_link_hash_table *htab;
-
-  htab = mips_elf_hash_table (info);
-  s = mips_elf_rel_dyn_section (info, FALSE);
-  BFD_ASSERT (s != NULL);
-
-  if (htab->is_vxworks)
-    s->size += n * MIPS_ELF_RELA_SIZE (abfd);
-  else
-    {
-      if (s->size == 0)
-       {
-         /* Make room for a null element.  */
-         s->size += MIPS_ELF_REL_SIZE (abfd);
-         ++s->reloc_count;
-       }
-      s->size += n * MIPS_ELF_REL_SIZE (abfd);
-    }
-}
-
 /* Create a rel.dyn relocation for the dynamic linker to resolve.  REL
    is the original relocation, which is now being transformed into a
    dynamic relocation.  The ADDENDP is adjusted if necessary; the
@@ -7547,18 +7635,8 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
         executable and the shared library.  */
       if (!h->def_regular)
        {
-         /* We need .stub section.  */
-         h->root.u.def.section = htab->sstubs;
-         h->root.u.def.value = htab->sstubs->size;
-
-         /* XXX Write this stub address somewhere.  */
-         h->plt.offset = htab->sstubs->size;
-
-         /* Make room for this stub code.  */
-         htab->sstubs->size += htab->function_stub_size;
-
-         /* The last half word of the stub will be filled with the index
-            of this symbol in .dynsym section.  */
+         hmips->needs_lazy_stub = TRUE;
+         htab->lazy_stub_count++;
          return TRUE;
        }
     }
@@ -7757,15 +7835,6 @@ _bfd_mips_elf_always_size_sections (bfd *output_bfd,
                                    struct bfd_link_info *info)
 {
   asection *ri;
-
-  asection *s;
-  struct mips_got_info *g;
-  int i;
-  bfd_size_type loadable_size = 0;
-  bfd_size_type page_gotno;
-  bfd_size_type dynsymcount;
-  bfd *sub;
-  struct mips_elf_count_tls_arg count_tls_arg;
   struct mips_elf_link_hash_table *htab;
 
   htab = mips_elf_hash_table (info);
@@ -7780,29 +7849,40 @@ _bfd_mips_elf_always_size_sections (bfd *output_bfd,
     mips_elf_link_hash_traverse (mips_elf_hash_table (info),
                                 mips_elf_check_mips16_stubs, info);
 
+  return TRUE;
+}
+
+/* If the link uses a GOT, lay it out and work out its size.  */
+
+static bfd_boolean
+mips_elf_lay_out_got (bfd *output_bfd, struct bfd_link_info *info)
+{
+  bfd *dynobj;
+  asection *s;
+  struct mips_got_info *g;
+  int i;
+  bfd_size_type loadable_size = 0;
+  bfd_size_type page_gotno;
+  bfd *sub;
+  struct mips_elf_count_tls_arg count_tls_arg;
+  struct mips_elf_link_hash_table *htab;
+
+  htab = mips_elf_hash_table (info);
   s = htab->sgot;
   if (s == NULL)
     return TRUE;
 
+  dynobj = elf_hash_table (info)->dynobj;
   g = htab->got_info;
 
-  /* Calculate the total loadable size of the output.  That
-     will give us the maximum number of GOT_PAGE entries
-     required.  */
-  for (sub = info->input_bfds; sub; sub = sub->link_next)
-    {
-      asection *subsection;
+  /* Replace entries for indirect and warning symbols with entries for
+     the target symbol.  */
+  if (!mips_elf_resolve_final_got_entries (g))
+    return FALSE;
 
-      for (subsection = sub->sections;
-          subsection;
-          subsection = subsection->next)
-       {
-         if ((subsection->flags & SEC_ALLOC) == 0)
-           continue;
-         loadable_size += ((subsection->size + 0xf)
-                           &~ (bfd_size_type) 0xf);
-       }
-    }
+  /* Count the number of forced-local entries.  */
+  elf_link_hash_traverse (elf_hash_table (info),
+                         mips_elf_count_forced_local_got_symbols, g);
 
   /* There has to be a global GOT entry for every symbol with
      a dynamic symbol table index of DT_MIPS_GOTSYM or
@@ -7819,22 +7899,23 @@ _bfd_mips_elf_always_size_sections (bfd *output_bfd,
        relocations, then GLOBAL_GOTSYM will be NULL.  */
     i = 0;
 
-  /* Get a worst-case estimate of the number of dynamic symbols needed.
-     At this point, dynsymcount does not account for section symbols
-     and count_section_dynsyms may overestimate the number that will
-     be needed.  */
-  dynsymcount = (elf_hash_table (info)->dynsymcount
-                + count_section_dynsyms (output_bfd, info));
-
-  /* Determine the size of one stub entry.  */
-  htab->function_stub_size = (dynsymcount > 0x10000
-                             ? MIPS_FUNCTION_STUB_BIG_SIZE
-                             : MIPS_FUNCTION_STUB_NORMAL_SIZE);
+  /* Calculate the total loadable size of the output.  That
+     will give us the maximum number of GOT_PAGE entries
+     required.  */
+  for (sub = info->input_bfds; sub; sub = sub->link_next)
+    {
+      asection *subsection;
 
-  /* In the worst case, we'll get one stub per dynamic symbol, plus
-     one to account for the dummy entry at the end required by IRIX
-     rld.  */
-  loadable_size += htab->function_stub_size * (i + 1);
+      for (subsection = sub->sections;
+          subsection;
+          subsection = subsection->next)
+       {
+         if ((subsection->flags & SEC_ALLOC) == 0)
+           continue;
+         loadable_size += ((subsection->size + 0xf)
+                           &~ (bfd_size_type) 0xf);
+       }
+    }
 
   if (htab->is_vxworks)
     /* There's no need to allocate page entries for VxWorks; R_MIPS*_GOT16
@@ -7868,27 +7949,120 @@ _bfd_mips_elf_always_size_sections (bfd *output_bfd,
   g->tls_gotno += count_tls_arg.needed;
   s->size += g->tls_gotno * MIPS_ELF_GOT_SIZE (output_bfd);
 
-  mips_elf_resolve_final_got_entries (g);
-
   /* VxWorks does not support multiple GOTs.  It initializes $gp to
      __GOTT_BASE__[__GOTT_INDEX__], the value of which is set by the
      dynamic loader.  */
-  if (!htab->is_vxworks && s->size > MIPS_ELF_GOT_MAX_SIZE (info))
+  if (htab->is_vxworks)
+    {
+      /* VxWorks executables do not need a GOT.  */
+      if (info->shared)
+       {
+         /* Each VxWorks GOT entry needs an explicit relocation.  */
+         unsigned int count;
+
+         count = g->global_gotno + g->local_gotno - MIPS_RESERVED_GOTNO (info);
+         if (count)
+           mips_elf_allocate_dynamic_relocations (dynobj, info, count);
+       }
+    }
+  else if (s->size > MIPS_ELF_GOT_MAX_SIZE (info))
     {
       if (!mips_elf_multi_got (output_bfd, info, s, page_gotno))
        return FALSE;
     }
   else
     {
-      /* Set up TLS entries for the first GOT.  */
+      struct mips_elf_count_tls_arg arg;
+
+      /* Set up TLS entries.  */
       g->tls_assigned_gotno = g->global_gotno + g->local_gotno;
       htab_traverse (g->got_entries, mips_elf_initialize_tls_index, g);
+
+      /* Allocate room for the TLS relocations.  */
+      arg.info = info;
+      arg.needed = 0;
+      htab_traverse (g->got_entries, mips_elf_count_local_tls_relocs, &arg);
+      elf_link_hash_traverse (elf_hash_table (info),
+                             mips_elf_count_global_tls_relocs,
+                             &arg);
+      if (arg.needed)
+       mips_elf_allocate_dynamic_relocations (dynobj, info, arg.needed);
     }
-  htab->computed_got_sizes = TRUE;
 
   return TRUE;
 }
 
+/* Estimate the size of the .MIPS.stubs section.  */
+
+static void
+mips_elf_estimate_stub_size (bfd *output_bfd, struct bfd_link_info *info)
+{
+  struct mips_elf_link_hash_table *htab;
+  bfd_size_type dynsymcount;
+
+  htab = mips_elf_hash_table (info);
+  if (htab->lazy_stub_count == 0)
+    return;
+
+  /* IRIX rld assumes that a function stub isn't at the end of the .text
+     section, so add a dummy entry to the end.  */
+  htab->lazy_stub_count++;
+
+  /* Get a worst-case estimate of the number of dynamic symbols needed.
+     At this point, dynsymcount does not account for section symbols
+     and count_section_dynsyms may overestimate the number that will
+     be needed.  */
+  dynsymcount = (elf_hash_table (info)->dynsymcount
+                + count_section_dynsyms (output_bfd, info));
+
+  /* Determine the size of one stub entry.  */
+  htab->function_stub_size = (dynsymcount > 0x10000
+                             ? MIPS_FUNCTION_STUB_BIG_SIZE
+                             : MIPS_FUNCTION_STUB_NORMAL_SIZE);
+
+  htab->sstubs->size = htab->lazy_stub_count * htab->function_stub_size;
+}
+
+/* A mips_elf_link_hash_traverse callback for which DATA points to the
+   MIPS hash table.  If H needs a traditional MIPS lazy-binding stub,
+   allocate an entry in the stubs section.  */
+
+static bfd_boolean
+mips_elf_allocate_lazy_stub (struct mips_elf_link_hash_entry *h, void **data)
+{
+  struct mips_elf_link_hash_table *htab;
+
+  htab = (struct mips_elf_link_hash_table *) data;
+  if (h->needs_lazy_stub)
+    {
+      h->root.root.u.def.section = htab->sstubs;
+      h->root.root.u.def.value = htab->sstubs->size;
+      h->root.plt.offset = htab->sstubs->size;
+      htab->sstubs->size += htab->function_stub_size;
+    }
+  return TRUE;
+}
+
+/* Allocate offsets in the stubs section to each symbol that needs one.
+   Set the final size of the .MIPS.stub section.  */
+
+static void
+mips_elf_lay_out_lazy_stubs (struct bfd_link_info *info)
+{
+  struct mips_elf_link_hash_table *htab;
+
+  htab = mips_elf_hash_table (info);
+  if (htab->lazy_stub_count == 0)
+    return;
+
+  htab->sstubs->size = 0;
+  mips_elf_link_hash_traverse (mips_elf_hash_table (info),
+                              mips_elf_allocate_lazy_stub, htab);
+  htab->sstubs->size += htab->function_stub_size;
+  BFD_ASSERT (htab->sstubs->size
+             == htab->lazy_stub_count * htab->function_stub_size);
+}
+
 /* Set the sizes of the dynamic sections.  */
 
 bfd_boolean
@@ -7896,7 +8070,7 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
                                     struct bfd_link_info *info)
 {
   bfd *dynobj;
-  asection *s, *sreldyn;
+  asection *s;
   bfd_boolean reltext;
   struct mips_elf_link_hash_table *htab;
 
@@ -7918,19 +8092,20 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
        }
       }
 
-  /* IRIX rld assumes that the function stub isn't at the end
-     of the .text section, so add a dummy entry to the end.  */
-  if (htab->sstubs && htab->sstubs->size > 0)
-    htab->sstubs->size += htab->function_stub_size;
-
   /* Allocate space for global sym dynamic relocs.  */
   elf_link_hash_traverse (&htab->root, allocate_dynrelocs, (PTR) info);
 
+  mips_elf_estimate_stub_size (output_bfd, info);
+
+  if (!mips_elf_lay_out_got (output_bfd, info))
+    return FALSE;
+
+  mips_elf_lay_out_lazy_stubs (info);
+
   /* The check_relocs and adjust_dynamic_symbol entry points have
      determined the sizes of the various dynamic sections.  Allocate
      memory for them.  */
   reltext = FALSE;
-  sreldyn = NULL;
   for (s = dynobj->sections; s != NULL; s = s->next)
     {
       const char *name;
@@ -7978,88 +8153,6 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
              info->combreloc = 0;
            }
        }
-      else if (htab->is_vxworks && strcmp (name, ".got") == 0)
-       {
-         /* Executables do not need a GOT.  */
-         if (info->shared)
-           {
-             /* Allocate relocations for all but the reserved entries.  */
-             unsigned int count;
-
-             count = (htab->got_info->global_gotno
-                      + htab->got_info->local_gotno
-                      - MIPS_RESERVED_GOTNO (info));
-             mips_elf_allocate_dynamic_relocations (dynobj, info, count);
-           }
-       }
-      else if (!htab->is_vxworks && CONST_STRNEQ (name, ".got"))
-       {
-         /* _bfd_mips_elf_always_size_sections() has already done
-            most of the work, but some symbols may have been mapped
-            to versions that we must now resolve in the got_entries
-            hash tables.  */
-         struct mips_got_info *gg = htab->got_info;
-         struct mips_got_info *g = gg;
-         struct mips_elf_set_global_got_offset_arg set_got_offset_arg;
-         unsigned int needed_relocs = 0;
-
-         if (gg->next)
-           {
-             set_got_offset_arg.value = MIPS_ELF_GOT_SIZE (output_bfd);
-             set_got_offset_arg.info = info;
-
-             /* NOTE 2005-02-03: How can this call, or the next, ever
-                find any indirect entries to resolve?  They were all
-                resolved in mips_elf_multi_got.  */
-             mips_elf_resolve_final_got_entries (gg);
-             for (g = gg->next; g && g->next != gg; g = g->next)
-               {
-                 unsigned int save_assign;
-
-                 mips_elf_resolve_final_got_entries (g);
-
-                 /* Assign offsets to global GOT entries.  */
-                 save_assign = g->assigned_gotno;
-                 g->assigned_gotno = g->local_gotno;
-                 set_got_offset_arg.g = g;
-                 set_got_offset_arg.needed_relocs = 0;
-                 htab_traverse (g->got_entries,
-                                mips_elf_set_global_got_offset,
-                                &set_got_offset_arg);
-                 needed_relocs += set_got_offset_arg.needed_relocs;
-                 BFD_ASSERT (g->assigned_gotno - g->local_gotno
-                             <= g->global_gotno);
-
-                 g->assigned_gotno = save_assign;
-                 if (info->shared)
-                   {
-                     needed_relocs += g->local_gotno - g->assigned_gotno;
-                     BFD_ASSERT (g->assigned_gotno == g->next->local_gotno
-                                 + g->next->global_gotno
-                                 + g->next->tls_gotno
-                                 + MIPS_RESERVED_GOTNO (info));
-                   }
-               }
-           }
-         else
-           {
-             struct mips_elf_count_tls_arg arg;
-             arg.info = info;
-             arg.needed = 0;
-
-             htab_traverse (gg->got_entries, mips_elf_count_local_tls_relocs,
-                            &arg);
-             elf_link_hash_traverse (elf_hash_table (info),
-                                     mips_elf_count_global_tls_relocs,
-                                     &arg);
-
-             needed_relocs += arg.needed;
-           }
-
-         if (needed_relocs)
-           mips_elf_allocate_dynamic_relocations (dynobj, info,
-                                                  needed_relocs);
-       }
       else if (! info->shared
               && ! mips_elf_hash_table (info)->use_rld_obj_head
               && CONST_STRNEQ (name, ".rld_map"))
@@ -8072,6 +8165,7 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
               && CONST_STRNEQ (name, ".compact_rel"))
        s->size += mips_elf_hash_table (info)->compact_rel_size;
       else if (! CONST_STRNEQ (name, ".init")
+              && s != htab->sgot
               && s != htab->sgotplt
               && s != htab->splt
               && s != htab->sstubs)
@@ -8089,14 +8183,6 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
       if ((s->flags & SEC_HAS_CONTENTS) == 0)
        continue;
 
-      /* Allocate memory for this section last, since we may increase its
-        size above.  */
-      if (strcmp (name, MIPS_ELF_REL_DYN_NAME (info)) == 0)
-       {
-         sreldyn = s;
-         continue;
-       }
-
       /* Allocate memory for the section contents.  */
       s->contents = bfd_zalloc (dynobj, s->size);
       if (s->contents == NULL)
@@ -8106,17 +8192,6 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
        }
     }
 
-  /* Allocate memory for the .rel(a).dyn section.  */
-  if (sreldyn != NULL)
-    {
-      sreldyn->contents = bfd_zalloc (dynobj, sreldyn->size);
-      if (sreldyn->contents == NULL)
-       {
-         bfd_set_error (bfd_error_no_memory);
-         return FALSE;
-       }
-    }
-
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       /* Add some entries to the .dynamic section.  We fill in the
@@ -10193,91 +10268,6 @@ _bfd_mips_elf_copy_indirect_symbol (struct bfd_link_info *info,
   if (dirmips->tls_type == 0)
     dirmips->tls_type = indmips->tls_type;
 }
-
-void
-_bfd_mips_elf_hide_symbol (struct bfd_link_info *info,
-                          struct elf_link_hash_entry *entry,
-                          bfd_boolean force_local)
-{
-  bfd *dynobj;
-  struct mips_got_info *g;
-  struct mips_elf_link_hash_entry *h;
-  struct mips_elf_link_hash_table *htab;
-
-  h = (struct mips_elf_link_hash_entry *) entry;
-  if (h->forced_local)
-    return;
-  h->forced_local = force_local;
-
-  dynobj = elf_hash_table (info)->dynobj;
-  htab = mips_elf_hash_table (info);
-  if (dynobj != NULL
-      && force_local
-      && h->root.type != STT_TLS
-      && htab->got_info != NULL)
-    {
-      g = htab->got_info;
-      if (g->next)
-       {
-         struct mips_got_entry e;
-         struct mips_got_info *gg = g;
-
-         /* Since we're turning what used to be a global symbol into a
-            local one, bump up the number of local entries of each GOT
-            that had an entry for it.  This will automatically decrease
-            the number of global entries, since global_gotno is actually
-            the upper limit of global entries.  */
-         e.abfd = dynobj;
-         e.symndx = -1;
-         e.d.h = h;
-         e.tls_type = 0;
-
-         for (g = g->next; g != gg; g = g->next)
-           if (htab_find (g->got_entries, &e))
-             {
-               BFD_ASSERT (g->global_gotno > 0);
-               g->local_gotno++;
-               g->global_gotno--;
-             }
-
-         /* If this was a global symbol forced into the primary GOT, we
-            no longer need an entry for it.  We can't release the entry
-            at this point, but we must at least stop counting it as one
-            of the symbols that required a forced got entry.  */
-         if (h->root.got.offset == 2)
-           {
-             BFD_ASSERT (gg->assigned_gotno > 0);
-             gg->assigned_gotno--;
-           }
-       }
-      else if (h->root.got.offset == 1)
-       {
-         /* check_relocs didn't know that this symbol would be
-            forced-local, so add an extra local got entry.  */
-         g->local_gotno++;
-         if (htab->computed_got_sizes)
-           {
-             /* We'll have treated this symbol as global rather
-                than local.  */
-             BFD_ASSERT (g->global_gotno > 0);
-             g->global_gotno--;
-           }
-       }
-      else if (htab->is_vxworks && h->root.needs_plt)
-       {
-         /* check_relocs didn't know that this symbol would be
-            forced-local, so add an extra local got entry.  */
-         g->local_gotno++;
-         if (htab->computed_got_sizes)
-           /* The symbol is only used in call relocations, so we'll
-              have assumed it only needs a .got.plt entry.  Increase
-              the size of .got accordingly.  */
-           htab->sgot->size += MIPS_ELF_GOT_SIZE (dynobj);
-        }
-    }
-
-  _bfd_elf_link_hash_hide_symbol (info, &h->root, force_local);
-}
 \f
 #define PDR_SIZE 32
 
@@ -10734,7 +10724,6 @@ _bfd_mips_elf_link_hash_table_create (bfd *abfd)
   ret->use_rld_obj_head = FALSE;
   ret->rld_value = 0;
   ret->mips16_stubs_seen = FALSE;
-  ret->computed_got_sizes = FALSE;
   ret->is_vxworks = FALSE;
   ret->small_data_overflow_reported = FALSE;
   ret->srelbss = NULL;
@@ -10748,6 +10737,7 @@ _bfd_mips_elf_link_hash_table_create (bfd *abfd)
   ret->got_info = NULL;
   ret->plt_header_size = 0;
   ret->plt_entry_size = 0;
+  ret->lazy_stub_count = 0;
   ret->function_stub_size = 0;
 
   return &ret->root.root;
index 79d234a..659c418 100644 (file)
@@ -81,8 +81,6 @@ extern bfd_boolean _bfd_mips_elf_gc_sweep_hook
 extern void _bfd_mips_elf_copy_indirect_symbol
   (struct bfd_link_info *, struct elf_link_hash_entry *,
    struct elf_link_hash_entry *);
-extern void _bfd_mips_elf_hide_symbol
-  (struct bfd_link_info *, struct elf_link_hash_entry *, bfd_boolean);
 extern bfd_boolean _bfd_mips_elf_ignore_discarded_relocs
   (asection *);
 extern bfd_boolean _bfd_mips_elf_find_nearest_line
index 7a90aad..529643b 100644 (file)
@@ -1,5 +1,22 @@
 2008-08-07  Richard Sandiford  <rdsandiford@googlemail.com>
 
+       * ld-mips-elf/tlsdyn-o32-2.got, ld-mips-elf/tlsdyn-o32-3.got,
+       ld-mips-elf/tlsdyn-o32-2.d, ld-mips-elf/tlsdyn-o32-3.d: Change the
+       GOT layout as follows:
+
+                BEFORE                  AFTER
+          +0x08 %call16(__tls_get_addr) %call16(__tls_get_addr)
+          +0x0c %tlsldm(tlsbin_ld)      %gottprel(tlsvar_ie)
+          +0x10   "  "                  %tlsgd(tlsvar_gd)
+          +0x14 %tlsgd(tlsvar_gd)          "  "
+          +0x18   "  "                  %tlsgd(tlsbin_gd)
+          +0x1c %gottprel(tlsvar_ie)       "  "
+          +0x20 %tlsgd(tlsbin_gd)       %tlsldm(tlsbin_ld)
+          +0x24   "  "                     "  "       
+          +0x28 %gottprel(tlsbin_ie)    %gottprel(tlsbin_ie)
+
+2008-08-07  Richard Sandiford  <rdsandiford@googlemail.com>
+
        * ld-mips-elf/reloc-estimate-1.d, ld-mips-elf/reloc-estimate-1.ld,
        ld-mips-elf/reloc-estimate-1a.s, ld-mips-elf/reloc-estimate-1b.s:
        New test.
index bf803c8..e1f76b5 100644 (file)
@@ -12,19 +12,19 @@ Disassembly of section .text:
   .*:  03a0f021        move    s8,sp
   .*:  afbc0000        sw      gp,0\(sp\)
   .*:  8f998018        lw      t9,-32744\(gp\)
-  .*:  27848030        addiu   a0,gp,-32720
+  .*:  27848028        addiu   a0,gp,-32728
   .*:  0320f809        jalr    t9
   .*:  00000000        nop
   .*:  8fdc0000        lw      gp,0\(s8\)
   .*:  00000000        nop
   .*:  8f998018        lw      t9,-32744\(gp\)
-  .*:  27848024        addiu   a0,gp,-32732
+  .*:  27848020        addiu   a0,gp,-32736
   .*:  0320f809        jalr    t9
   .*:  00000000        nop
   .*:  8fdc0000        lw      gp,0\(s8\)
   .*:  00000000        nop
   .*:  8f998018        lw      t9,-32744\(gp\)
-  .*:  2784801c        addiu   a0,gp,-32740
+  .*:  27848030        addiu   a0,gp,-32720
   .*:  0320f809        jalr    t9
   .*:  00000000        nop
   .*:  8fdc0000        lw      gp,0\(s8\)
@@ -36,7 +36,7 @@ Disassembly of section .text:
   .*:  8f838038        lw      v1,-32712\(gp\)
   .*:  00000000        nop
   .*:  00621821        addu    v1,v1,v0
-  .*:  8f83802c        lw      v1,-32724\(gp\)
+  .*:  8f83801c        lw      v1,-32740\(gp\)
   .*:  00000000        nop
   .*:  00621821        addu    v1,v1,v0
   .*:  7c02283b        rdhwr   v0,\$5
@@ -62,19 +62,19 @@ Disassembly of section .text:
   .*:  03a0f021        move    s8,sp
   .*:  afbc0000        sw      gp,0\(sp\)
   .*:  8f998018        lw      t9,-32744\(gp\)
-  .*:  27848030        addiu   a0,gp,-32720
+  .*:  27848028        addiu   a0,gp,-32728
   .*:  0320f809        jalr    t9
   .*:  00000000        nop
   .*:  8fdc0000        lw      gp,0\(s8\)
   .*:  00000000        nop
   .*:  8f998018        lw      t9,-32744\(gp\)
-  .*:  27848024        addiu   a0,gp,-32732
+  .*:  27848020        addiu   a0,gp,-32736
   .*:  0320f809        jalr    t9
   .*:  00000000        nop
   .*:  8fdc0000        lw      gp,0\(s8\)
   .*:  00000000        nop
   .*:  8f998018        lw      t9,-32744\(gp\)
-  .*:  2784801c        addiu   a0,gp,-32740
+  .*:  27848030        addiu   a0,gp,-32720
   .*:  0320f809        jalr    t9
   .*:  00000000        nop
   .*:  8fdc0000        lw      gp,0\(s8\)
@@ -86,7 +86,7 @@ Disassembly of section .text:
   .*:  8f838038        lw      v1,-32712\(gp\)
   .*:  00000000        nop
   .*:  00621821        addu    v1,v1,v0
-  .*:  8f83802c        lw      v1,-32724\(gp\)
+  .*:  8f83801c        lw      v1,-32740\(gp\)
   .*:  00000000        nop
   .*:  00621821        addu    v1,v1,v0
   .*:  7c02283b        rdhwr   v0,\$5
index e397b2f..c5516c5 100644 (file)
@@ -4,16 +4,16 @@
 DYNAMIC RELOCATION RECORDS
 OFFSET   TYPE              VALUE 
 00000000 R_MIPS_NONE       \*ABS\*
-10000040 R_MIPS_TLS_DTPMOD32  tlsbin_gd
-10000044 R_MIPS_TLS_DTPREL32  tlsbin_gd
-10000034 R_MIPS_TLS_DTPMOD32  tlsvar_gd
-10000038 R_MIPS_TLS_DTPREL32  tlsvar_gd
-1000003c R_MIPS_TLS_TPREL32  tlsvar_ie
+10000038 R_MIPS_TLS_DTPMOD32  tlsbin_gd
+1000003c R_MIPS_TLS_DTPREL32  tlsbin_gd
+10000030 R_MIPS_TLS_DTPMOD32  tlsvar_gd
+10000034 R_MIPS_TLS_DTPREL32  tlsvar_gd
+1000002c R_MIPS_TLS_TPREL32  tlsvar_ie
 10000048 R_MIPS_TLS_TPREL32  tlsbin_ie
 
 
 Contents of section .got:
- 10000020 00000000 80000000 0040053c 00000001  .*
+ 10000020 00000000 80000000 0040053c 00000000  .*
  10000030 00000000 00000000 00000000 00000000  .*
- 10000040 00000000 00000000 00000000 00000000  .*
+ 10000040 00000001 00000000 00000000 00000000  .*
  10000050 00000000 00000000                    .*
index 4a3a0e1..27db816 100644 (file)
@@ -12,19 +12,19 @@ Disassembly of section .text:
   .*:  03a0f021        move    s8,sp
   .*:  afbc0000        sw      gp,0\(sp\)
   .*:  8f998018        lw      t9,-32744\(gp\)
-  .*:  27848030        addiu   a0,gp,-32720
+  .*:  27848028        addiu   a0,gp,-32728
   .*:  0320f809        jalr    t9
   .*:  00000000        nop
   .*:  8fdc0000        lw      gp,0\(s8\)
   .*:  00000000        nop
   .*:  8f998018        lw      t9,-32744\(gp\)
-  .*:  27848024        addiu   a0,gp,-32732
+  .*:  27848020        addiu   a0,gp,-32736
   .*:  0320f809        jalr    t9
   .*:  00000000        nop
   .*:  8fdc0000        lw      gp,0\(s8\)
   .*:  00000000        nop
   .*:  8f998018        lw      t9,-32744\(gp\)
-  .*:  2784801c        addiu   a0,gp,-32740
+  .*:  27848030        addiu   a0,gp,-32720
   .*:  0320f809        jalr    t9
   .*:  00000000        nop
   .*:  8fdc0000        lw      gp,0\(s8\)
@@ -36,7 +36,7 @@ Disassembly of section .text:
   .*:  8f838038        lw      v1,-32712\(gp\)
   .*:  00000000        nop
   .*:  00621821        addu    v1,v1,v0
-  .*:  8f83802c        lw      v1,-32724\(gp\)
+  .*:  8f83801c        lw      v1,-32740\(gp\)
   .*:  00000000        nop
   .*:  00621821        addu    v1,v1,v0
   .*:  7c02283b        rdhwr   v0,\$5
@@ -58,19 +58,19 @@ Disassembly of section .text:
   .*:  03a0f021        move    s8,sp
   .*:  afbc0000        sw      gp,0\(sp\)
   .*:  8f998018        lw      t9,-32744\(gp\)
-  .*:  27848030        addiu   a0,gp,-32720
+  .*:  27848028        addiu   a0,gp,-32728
   .*:  0320f809        jalr    t9
   .*:  00000000        nop
   .*:  8fdc0000        lw      gp,0\(s8\)
   .*:  00000000        nop
   .*:  8f998018        lw      t9,-32744\(gp\)
-  .*:  27848024        addiu   a0,gp,-32732
+  .*:  27848020        addiu   a0,gp,-32736
   .*:  0320f809        jalr    t9
   .*:  00000000        nop
   .*:  8fdc0000        lw      gp,0\(s8\)
   .*:  00000000        nop
   .*:  8f998018        lw      t9,-32744\(gp\)
-  .*:  2784801c        addiu   a0,gp,-32740
+  .*:  27848030        addiu   a0,gp,-32720
   .*:  0320f809        jalr    t9
   .*:  00000000        nop
   .*:  8fdc0000        lw      gp,0\(s8\)
@@ -82,7 +82,7 @@ Disassembly of section .text:
   .*:  8f838038        lw      v1,-32712\(gp\)
   .*:  00000000        nop
   .*:  00621821        addu    v1,v1,v0
-  .*:  8f83802c        lw      v1,-32724\(gp\)
+  .*:  8f83801c        lw      v1,-32740\(gp\)
   .*:  00000000        nop
   .*:  00621821        addu    v1,v1,v0
   .*:  7c02283b        rdhwr   v0,\$5
index fe77221..54f491e 100644 (file)
@@ -4,16 +4,16 @@
 DYNAMIC RELOCATION RECORDS
 OFFSET   TYPE              VALUE 
 00000000 R_MIPS_NONE       \*ABS\*
-10000040 R_MIPS_TLS_DTPMOD32  tlsbin_gd
-10000044 R_MIPS_TLS_DTPREL32  tlsbin_gd
-10000034 R_MIPS_TLS_DTPMOD32  tlsvar_gd
-10000038 R_MIPS_TLS_DTPREL32  tlsvar_gd
-1000003c R_MIPS_TLS_TPREL32  tlsvar_ie
+10000038 R_MIPS_TLS_DTPMOD32  tlsbin_gd
+1000003c R_MIPS_TLS_DTPREL32  tlsbin_gd
+10000030 R_MIPS_TLS_DTPMOD32  tlsvar_gd
+10000034 R_MIPS_TLS_DTPREL32  tlsvar_gd
+1000002c R_MIPS_TLS_TPREL32  tlsvar_ie
 10000048 R_MIPS_TLS_TPREL32  tlsbin_ie
 
 
 Contents of section .got:
- 10000020 00000000 80000000 004005ec 00000001  .*
+ 10000020 00000000 80000000 004005ec 00000000  .*
  10000030 00000000 00000000 00000000 00000000  .*
- 10000040 00000000 00000000 00000000 00000000  .*
+ 10000040 00000001 00000000 00000000 00000000  .*
  10000050 00000000 00000000                    .*