bfd/
authorRichard Sandiford <rdsandiford@googlemail.com>
Mon, 11 Feb 2013 18:06:10 +0000 (18:06 +0000)
committerRichard Sandiford <rdsandiford@googlemail.com>
Mon, 11 Feb 2013 18:06:10 +0000 (18:06 +0000)
* elfxx-mips.c (mips_got_info): Remove bfd2got.
(mips_elf_bfd2got_hash): Delete.
(mips_elf_got_per_bfd_arg): Remove bfd2got.
(mips_elf_replace_bfd_got, mips_elf_count_got_entries): New functions.
(mips_elf_global_got_index, mips_elf_create_local_got_entry): Use
g->next to test for the multigot case.  Use mips_elf_bfd_got rather
than mips_elf_got_for_ibfd.
(mips_elf_bfd2got_entry_hash, mips_elf_bfd2got_entry_eq)
(mips_elf_got_for_ibfd, mips_elf_get_got_for_bfd): Delete.
(mips_elf_make_got_per_bfd): Replace with...
(mips_elf_add_got_entry): ...this new function.
(mips_elf_make_got_pages_per_bfd): Replace with...
(mips_elf_add_got_page_entry): ...this new function.
(mips_elf_merge_got_with): Replace bfd2got argument with separate
bfd and GOT arguments.  Use mips_elf_add_got_entry and
mips_elf_add_got_page_entry instead of mips_elf_make_got_per_bfd
and mips_elf_make_got_pages_per_bfd.  Use mips_elf_replace_bfd_got
to set the BFD's GOT and free the old table.
(mips_elf_merge_got): Replace bfd2got argument with separate
bfd and GOT arguments.  Apply mips_elf_resolve_final_got_entries.
Use mips_elf_count_got_entries to count the number of entries in
each GOT.  Update the calls to mips_elf_merge_got_with.
(mips_elf_adjust_gp): Use g->next to test for the multigot case.
Use mips_elf_bfd_got rather than mips_elf_got_for_ibfd.
(mips_elf_multi_got): Don't create the bfd2got hash table.
Replace hash table traversal with a walk over the input bfds,
updating the call to mips_elf_merge_got.  Use mips_elf_replace_bfd_got
to set the output bfd's GOT.
(mips_elf_lay_out_got): Rename "sub" to "ibfd".  Record that all
bfds use the master GOT in the single-GOT case.
(_bfd_mips_elf_finish_dynamic_sections): Use mips_elf_bfd_got
rather than mips_elf_got_for_ibfd.

ld/testsuite/
* ld-mips-elf/tls-hidden4.got, ld-mips-elf/tls-multi-got-1.d,
ld-mips-elf/tls-multi-got-1.got: Update for changes in the order
that symbols are added to per-bfd GOTs.

bfd/ChangeLog
bfd/elfxx-mips.c
ld/testsuite/ChangeLog
ld/testsuite/ld-mips-elf/tls-hidden4.got
ld/testsuite/ld-mips-elf/tls-multi-got-1.d
ld/testsuite/ld-mips-elf/tls-multi-got-1.got

index dbfff43..ed3ab95 100644 (file)
@@ -1,5 +1,40 @@
 2013-02-11  Richard Sandiford  <rdsandiford@googlemail.com>
 
+       * elfxx-mips.c (mips_got_info): Remove bfd2got.
+       (mips_elf_bfd2got_hash): Delete.
+       (mips_elf_got_per_bfd_arg): Remove bfd2got.
+       (mips_elf_replace_bfd_got, mips_elf_count_got_entries): New functions.
+       (mips_elf_global_got_index, mips_elf_create_local_got_entry): Use
+       g->next to test for the multigot case.  Use mips_elf_bfd_got rather
+       than mips_elf_got_for_ibfd.
+       (mips_elf_bfd2got_entry_hash, mips_elf_bfd2got_entry_eq)
+       (mips_elf_got_for_ibfd, mips_elf_get_got_for_bfd): Delete.
+       (mips_elf_make_got_per_bfd): Replace with...
+       (mips_elf_add_got_entry): ...this new function.
+       (mips_elf_make_got_pages_per_bfd): Replace with...
+       (mips_elf_add_got_page_entry): ...this new function.
+       (mips_elf_merge_got_with): Replace bfd2got argument with separate
+       bfd and GOT arguments.  Use mips_elf_add_got_entry and
+       mips_elf_add_got_page_entry instead of mips_elf_make_got_per_bfd
+       and mips_elf_make_got_pages_per_bfd.  Use mips_elf_replace_bfd_got
+       to set the BFD's GOT and free the old table.
+       (mips_elf_merge_got): Replace bfd2got argument with separate
+       bfd and GOT arguments.  Apply mips_elf_resolve_final_got_entries.
+       Use mips_elf_count_got_entries to count the number of entries in
+       each GOT.  Update the calls to mips_elf_merge_got_with.
+       (mips_elf_adjust_gp): Use g->next to test for the multigot case.
+       Use mips_elf_bfd_got rather than mips_elf_got_for_ibfd.
+       (mips_elf_multi_got): Don't create the bfd2got hash table.
+       Replace hash table traversal with a walk over the input bfds,
+       updating the call to mips_elf_merge_got.  Use mips_elf_replace_bfd_got
+       to set the output bfd's GOT.
+       (mips_elf_lay_out_got): Rename "sub" to "ibfd".  Record that all
+       bfds use the master GOT in the single-GOT case.
+       (_bfd_mips_elf_finish_dynamic_sections): Use mips_elf_bfd_got
+       rather than mips_elf_got_for_ibfd.
+
+2013-02-11  Richard Sandiford  <rdsandiford@googlemail.com>
+
        * elfxx-mips.c (mips_elf_obj_tdata): Add a got field.
        (mips_elf_bfd_got, mips_elf_record_got_entry): New functions.
        (mips_elf_record_global_got_symbol): Update the hash entry before
index 4302639..64fa382 100644 (file)
@@ -161,9 +161,6 @@ struct mips_got_info
   struct htab *got_entries;
   /* A hash table of mips_got_page_entry structures.  */
   struct htab *got_page_entries;
-  /* A hash table mapping input bfds to other mips_got_info.  NULL
-     unless multi-got was necessary.  */
-  struct htab *bfd2got;
   /* In multi-got links, a pointer to the next got (err, rather, most
      of the time, it points to the previous got).  */
   struct mips_got_info *next;
@@ -174,21 +171,10 @@ struct mips_got_info
   bfd_vma tls_ldm_offset;
 };
 
-/* Map an input bfd to a got in a multi-got link.  */
-
-struct mips_elf_bfd2got_hash
-{
-  bfd *bfd;
-  struct mips_got_info *g;
-};
-
-/* Structure passed when traversing the bfd2got hash table, used to
-   create and merge bfd's gots.  */
+/* Structure passed when merging bfds' gots.  */
 
 struct mips_elf_got_per_bfd_arg
 {
-  /* A hashtable that maps bfds to gots.  */
-  htab_t bfd2got;
   /* The output bfd.  */
   bfd *obfd;
   /* The link information.  */
@@ -696,8 +682,6 @@ static bfd_boolean mips_elf_create_dynamic_relocation
    bfd_vma *, asection *);
 static bfd_vma mips_elf_adjust_gp
   (bfd *, struct mips_got_info *, bfd *);
-static struct mips_got_info *mips_elf_got_for_ibfd
-  (struct mips_got_info *, bfd *);
 
 /* This will be used when we sort the dynamic relocation records.  */
 static bfd *reldyn_sorting_bfd;
@@ -2903,6 +2887,25 @@ mips_elf_bfd_got (bfd *abfd, bfd_boolean create_p)
   return tdata->got;
 }
 
+/* Record that ABFD should use output GOT G.  */
+
+static void
+mips_elf_replace_bfd_got (bfd *abfd, struct mips_got_info *g)
+{
+  struct mips_elf_obj_tdata *tdata;
+
+  BFD_ASSERT (is_mips_elf (abfd));
+  tdata = mips_elf_tdata (abfd);
+  if (tdata->got)
+    {
+      /* The GOT structure itself and the hash table entries are
+        allocated to a bfd, but the hash tables aren't.  */
+      htab_delete (tdata->got->got_entries);
+      htab_delete (tdata->got->got_page_entries);
+    }
+  tdata->got = g;
+}
+
 /* Return the dynamic relocation section.  If it doesn't exist, try to
    create a new it if CREATE_P, otherwise return NULL.  Also return NULL
    if creation fails.  */
@@ -3036,6 +3039,23 @@ mips_elf_count_got_entry (struct bfd_link_info *info,
     g->global_gotno += 1;
 }
 
+/* A htab_traverse callback.  Count the number of GOT entries and
+   TLS relocations required for the GOT entry in *ENTRYP.  DATA points
+   to a mips_elf_traverse_got_arg structure.  */
+
+static int
+mips_elf_count_got_entries (void **entryp, void *data)
+{
+  struct mips_got_entry *entry;
+  struct mips_elf_traverse_got_arg *arg;
+
+  entry = (struct mips_got_entry *) *entryp;
+  arg = (struct mips_elf_traverse_got_arg *) data;
+  mips_elf_count_got_entry (arg->info, arg->g, entry);
+
+  return 1;
+}
+
 /* A htab_traverse callback.  If *SLOT describes a GOT entry for a local
    symbol, count the number of GOT entries and TLS relocations that it
    requires.  DATA points to a mips_elf_traverse_got_arg structure.  */
@@ -3365,13 +3385,14 @@ mips_elf_global_got_index (bfd *abfd, bfd *ibfd, struct elf_link_hash_entry *h,
   BFD_ASSERT (htab != NULL);
 
   gg = g = htab->got_info;
-  if (g->bfd2got && ibfd)
+  if (g->next && ibfd)
     {
       struct mips_got_entry e, *p;
 
       BFD_ASSERT (h->dynindx >= 0);
 
-      g = mips_elf_got_for_ibfd (g, ibfd);
+      g = mips_elf_bfd_got (ibfd, FALSE);
+      BFD_ASSERT (g);
       if (g->next != gg || TLS_RELOC_P (r_type))
        {
          e.abfd = ibfd;
@@ -3535,10 +3556,10 @@ mips_elf_create_local_got_entry (bfd *abfd, struct bfd_link_info *info,
   entry.d.address = value;
   entry.tls_type = mips_elf_reloc_tls_type (r_type);
 
-  g = mips_elf_got_for_ibfd (htab->got_info, ibfd);
+  g = mips_elf_bfd_got (ibfd, FALSE);
   if (g == NULL)
     {
-      g = mips_elf_got_for_ibfd (htab->got_info, abfd);
+      g = mips_elf_bfd_got (abfd, FALSE);
       BFD_ASSERT (g != NULL);
     }
 
@@ -4163,147 +4184,70 @@ mips_elf_count_got_symbols (struct mips_elf_link_hash_entry *h, void *data)
   return 1;
 }
 \f
-/* Compute the hash value of the bfd in a bfd2got hash entry.  */
-
-static hashval_t
-mips_elf_bfd2got_entry_hash (const void *entry_)
-{
-  const struct mips_elf_bfd2got_hash *entry
-    = (struct mips_elf_bfd2got_hash *)entry_;
-
-  return entry->bfd->id;
-}
-
-/* Check whether two hash entries have the same bfd.  */
+/* A htab_traverse callback for GOT entries.  Add each one to the GOT
+   given in mips_elf_traverse_got_arg DATA.  Clear DATA->G on error.  */
 
 static int
-mips_elf_bfd2got_entry_eq (const void *entry1, const void *entry2)
+mips_elf_add_got_entry (void **entryp, void *data)
 {
-  const struct mips_elf_bfd2got_hash *e1
-    = (const struct mips_elf_bfd2got_hash *)entry1;
-  const struct mips_elf_bfd2got_hash *e2
-    = (const struct mips_elf_bfd2got_hash *)entry2;
-
-  return e1->bfd == e2->bfd;
-}
-
-/* In a multi-got link, determine the GOT to be used for IBFD.  G must
-   be the master GOT data.  */
-
-static struct mips_got_info *
-mips_elf_got_for_ibfd (struct mips_got_info *g, bfd *ibfd)
-{
-  struct mips_elf_bfd2got_hash e, *p;
-
-  if (! g->bfd2got)
-    return g;
-
-  e.bfd = ibfd;
-  p = htab_find (g->bfd2got, &e);
-  return p ? p->g : NULL;
-}
-
-/* Use BFD2GOT to find ABFD's got entry, creating one if none exists.
-   Return NULL if an error occured.  */
-
-static struct mips_got_info *
-mips_elf_get_got_for_bfd (struct htab *bfd2got, bfd *output_bfd,
-                         bfd *input_bfd)
-{
-  struct mips_elf_bfd2got_hash bfdgot_entry, *bfdgot;
-  void **bfdgotp;
-
-  bfdgot_entry.bfd = input_bfd;
-  bfdgotp = htab_find_slot (bfd2got, &bfdgot_entry, INSERT);
-  bfdgot = (struct mips_elf_bfd2got_hash *) *bfdgotp;
+  struct mips_got_entry *entry;
+  struct mips_elf_traverse_got_arg *arg;
+  void **slot;
 
-  if (bfdgot == NULL)
+  entry = (struct mips_got_entry *) *entryp;
+  arg = (struct mips_elf_traverse_got_arg *) data;
+  slot = htab_find_slot (arg->g->got_entries, entry, INSERT);
+  if (!slot)
     {
-      bfdgot = ((struct mips_elf_bfd2got_hash *)
-               bfd_alloc (output_bfd, sizeof (struct mips_elf_bfd2got_hash)));
-      if (bfdgot == NULL)
-       return NULL;
-
-      *bfdgotp = bfdgot;
-
-      bfdgot->bfd = input_bfd;
-      bfdgot->g = mips_elf_create_got_info (input_bfd, FALSE);
-      if (bfdgot->g == NULL)
-       return NULL;
+      arg->g = NULL;
+      return 0;
     }
-
-  return bfdgot->g;
-}
-
-/* A htab_traverse callback for the entries in the master got.
-   Create one separate got for each bfd that has entries in the global
-   got, such that we can tell how many local and global entries each
-   bfd requires.  */
-
-static int
-mips_elf_make_got_per_bfd (void **entryp, void *p)
-{
-  struct mips_got_entry *entry = (struct mips_got_entry *)*entryp;
-  struct mips_elf_got_per_bfd_arg *arg = (struct mips_elf_got_per_bfd_arg *)p;
-  struct mips_got_info *g;
-
-  g = mips_elf_get_got_for_bfd (arg->bfd2got, arg->obfd, entry->abfd);
-  if (g == NULL)
+  if (!*slot)
     {
-      arg->obfd = NULL;
-      return 0;
+      *slot = entry;
+      mips_elf_count_got_entry (arg->info, arg->g, entry);
     }
-
-  /* Insert the GOT entry in the bfd's got entry hash table.  */
-  entryp = htab_find_slot (g->got_entries, entry, INSERT);
-  if (*entryp != NULL)
-    return 1;
-
-  *entryp = entry;
-  mips_elf_count_got_entry (arg->info, g, entry);
-
   return 1;
 }
 
-/* A htab_traverse callback for the page entries in the master got.
-   Associate each page entry with the bfd's got.  */
+/* A htab_traverse callback for GOT page entries.  Add each one to the GOT
+   given in mips_elf_traverse_got_arg DATA.  Clear DATA->G on error.  */
 
 static int
-mips_elf_make_got_pages_per_bfd (void **entryp, void *p)
+mips_elf_add_got_page_entry (void **entryp, void *data)
 {
-  struct mips_got_page_entry *entry = (struct mips_got_page_entry *) *entryp;
-  struct mips_elf_got_per_bfd_arg *arg = (struct mips_elf_got_per_bfd_arg *) p;
-  struct mips_got_info *g;
+  struct mips_got_page_entry *entry;
+  struct mips_elf_traverse_got_arg *arg;
+  void **slot;
 
-  g = mips_elf_get_got_for_bfd (arg->bfd2got, arg->obfd, entry->abfd);
-  if (g == NULL)
+  entry = (struct mips_got_page_entry *) *entryp;
+  arg = (struct mips_elf_traverse_got_arg *) data;
+  slot = htab_find_slot (arg->g->got_page_entries, entry, INSERT);
+  if (!slot)
     {
-      arg->obfd = NULL;
+      arg->g = NULL;
       return 0;
     }
-
-  /* Insert the GOT entry in the bfd's got entry hash table.  */
-  entryp = htab_find_slot (g->got_page_entries, entry, INSERT);
-  if (*entryp != NULL)
-    return 1;
-
-  *entryp = entry;
-  g->page_gotno += entry->num_pages;
+  if (!*slot)
+    {
+      *slot = entry;
+      arg->g->page_gotno += entry->num_pages;
+    }
   return 1;
 }
 
-/* Consider merging the got described by BFD2GOT with TO, using the
-   information given by ARG.  Return -1 if this would lead to overflow,
-   1 if they were merged successfully, and 0 if a merge failed due to
-   lack of memory.  (These values are chosen so that nonnegative return
-   values can be returned by a htab_traverse callback.)  */
+/* Consider merging FROM, which is ABFD's GOT, into TO.  Return -1 if
+   this would lead to overflow, 1 if they were merged successfully,
+   and 0 if a merge failed due to lack of memory.  (These values are chosen
+   so that nonnegative return values can be returned by a htab_traverse
+   callback.)  */
 
 static int
-mips_elf_merge_got_with (struct mips_elf_bfd2got_hash *bfd2got,
+mips_elf_merge_got_with (bfd *abfd, struct mips_got_info *from,
                         struct mips_got_info *to,
                         struct mips_elf_got_per_bfd_arg *arg)
 {
-  struct mips_got_info *from = bfd2got->g;
+  struct mips_elf_traverse_got_arg tga;
   unsigned int estimate;
 
   /* Work out how many page entries we would need for the combined GOT.  */
@@ -4328,44 +4272,42 @@ mips_elf_merge_got_with (struct mips_elf_bfd2got_hash *bfd2got,
   if (estimate > arg->max_count)
     return -1;
 
-  /* Commit to the merge.  Record that TO is now the bfd for this got.  */
-  bfd2got->g = to;
-
   /* Transfer the bfd's got information from FROM to TO.  */
-  htab_traverse (from->got_entries, mips_elf_make_got_per_bfd, arg);
-  if (arg->obfd == NULL)
+  tga.info = arg->info;
+  tga.g = to;
+  htab_traverse (from->got_entries, mips_elf_add_got_entry, &tga);
+  if (!tga.g)
     return 0;
 
-  htab_traverse (from->got_page_entries, mips_elf_make_got_pages_per_bfd, arg);
-  if (arg->obfd == NULL)
+  htab_traverse (from->got_page_entries, mips_elf_add_got_page_entry, &tga);
+  if (!tga.g)
     return 0;
 
-  /* We don't have to worry about releasing memory of the actual
-     got entries, since they're all in the master got_entries hash
-     table anyway.  */
-  htab_delete (from->got_entries);
-  htab_delete (from->got_page_entries);
+  mips_elf_replace_bfd_got (abfd, to);
   return 1;
 }
 
-/* Attempt to merge gots of different input bfds.  Try to use as much
+/* Attempt to merge GOT G, which belongs to ABFD.  Try to use as much
    as possible of the primary got, since it doesn't require explicit
    dynamic relocations, but don't use bfds that would reference global
    symbols out of the addressable range.  Failing the primary got,
    attempt to merge with the current got, or finish the current got
    and then make make the new got current.  */
 
-static int
-mips_elf_merge_gots (void **bfd2got_, void *p)
+static bfd_boolean
+mips_elf_merge_got (bfd *abfd, struct mips_got_info *g,
+                   struct mips_elf_got_per_bfd_arg *arg)
 {
-  struct mips_elf_bfd2got_hash *bfd2got
-    = (struct mips_elf_bfd2got_hash *)*bfd2got_;
-  struct mips_elf_got_per_bfd_arg *arg = (struct mips_elf_got_per_bfd_arg *)p;
-  struct mips_got_info *g;
+  struct mips_elf_traverse_got_arg tga;
   unsigned int estimate;
   int result;
 
-  g = bfd2got->g;
+  if (!mips_elf_resolve_final_got_entries (g))
+    return FALSE;
+
+  tga.info = arg->info;
+  tga.g = g;
+  htab_traverse (g->got_entries, mips_elf_count_got_entries, &tga);
 
   /* Work out the number of page, local and TLS entries.  */
   estimate = arg->max_pages;
@@ -4385,12 +4327,12 @@ mips_elf_merge_gots (void **bfd2got_, void *p)
         a starting point for the primary GOT.  */
       if (!arg->primary)
        {
-         arg->primary = bfd2got->g;
-         return 1;
+         arg->primary = g;
+         return TRUE;
        }
 
       /* Try merging with the primary GOT.  */
-      result = mips_elf_merge_got_with (bfd2got, arg->primary, arg);
+      result = mips_elf_merge_got_with (abfd, g, arg->primary, arg);
       if (result >= 0)
        return result;
     }
@@ -4398,7 +4340,7 @@ mips_elf_merge_gots (void **bfd2got_, void *p)
   /* If we can merge with the last-created got, do it.  */
   if (arg->current)
     {
-      result = mips_elf_merge_got_with (bfd2got, arg->current, arg);
+      result = mips_elf_merge_got_with (abfd, g, arg->current, arg);
       if (result >= 0)
        return result;
     }
@@ -4409,7 +4351,7 @@ mips_elf_merge_gots (void **bfd2got_, void *p)
   g->next = arg->current;
   arg->current = g;
 
-  return 1;
+  return TRUE;
 }
 
 /* ENTRYP is a hash table entry for a mips_got_entry.  Set its gotidx
@@ -4592,10 +4534,10 @@ mips_elf_forbid_lazy_stubs (void **entryp, void *data)
 static bfd_vma
 mips_elf_adjust_gp (bfd *abfd, struct mips_got_info *g, bfd *ibfd)
 {
-  if (g->bfd2got == NULL)
+  if (!g->next)
     return 0;
 
-  g = mips_elf_got_for_ibfd (g, ibfd);
+  g = mips_elf_bfd_got (ibfd, FALSE);
   if (! g)
     return 0;
 
@@ -4619,34 +4561,16 @@ mips_elf_multi_got (bfd *abfd, struct bfd_link_info *info,
   struct mips_elf_traverse_got_arg tga;
   struct mips_got_info *g, *gg;
   unsigned int assign, needed_relocs;
-  bfd *dynobj;
+  bfd *dynobj, *ibfd;
 
   dynobj = elf_hash_table (info)->dynobj;
   htab = mips_elf_hash_table (info);
   BFD_ASSERT (htab != NULL);
 
   g = htab->got_info;
-  g->bfd2got = htab_try_create (1, mips_elf_bfd2got_entry_hash,
-                               mips_elf_bfd2got_entry_eq, NULL);
-  if (g->bfd2got == NULL)
-    return FALSE;
 
-  got_per_bfd_arg.bfd2got = g->bfd2got;
   got_per_bfd_arg.obfd = abfd;
   got_per_bfd_arg.info = info;
-
-  /* Count how many GOT entries each input bfd requires, creating a
-     map from bfd to got info while at that.  */
-  htab_traverse (g->got_entries, mips_elf_make_got_per_bfd, &got_per_bfd_arg);
-  if (got_per_bfd_arg.obfd == NULL)
-    return FALSE;
-
-  /* Also count how many page entries each input bfd requires.  */
-  htab_traverse (g->got_page_entries, mips_elf_make_got_pages_per_bfd,
-                &got_per_bfd_arg);
-  if (got_per_bfd_arg.obfd == NULL)
-    return FALSE;
-
   got_per_bfd_arg.current = NULL;
   got_per_bfd_arg.primary = NULL;
   got_per_bfd_arg.max_count = ((MIPS_ELF_GOT_MAX_SIZE (info)
@@ -4661,9 +4585,12 @@ mips_elf_multi_got (bfd *abfd, struct bfd_link_info *info,
   /* Try to merge the GOTs of input bfds together, as long as they
      don't seem to exceed the maximum GOT size, choosing one of them
      to be the primary GOT.  */
-  htab_traverse (g->bfd2got, mips_elf_merge_gots, &got_per_bfd_arg);
-  if (got_per_bfd_arg.obfd == NULL)
-    return FALSE;
+  for (ibfd = info->input_bfds; ibfd; ibfd = ibfd->link_next)
+    {
+      gg = mips_elf_bfd_got (ibfd, FALSE);
+      if (gg && !mips_elf_merge_got (ibfd, gg, &got_per_bfd_arg))
+       return FALSE;
+    }
 
   /* If we do not find any suitable primary GOT, create an empty one.  */
   if (got_per_bfd_arg.primary == NULL)
@@ -4681,23 +4608,7 @@ mips_elf_multi_got (bfd *abfd, struct bfd_link_info *info,
      didn't mark in check_relocs, and we want a quick way to find it.
      We can't just use gg->next because we're going to reverse the
      list.  */
-  {
-    struct mips_elf_bfd2got_hash *bfdgot;
-    void **bfdgotp;
-
-    bfdgot = (struct mips_elf_bfd2got_hash *)bfd_alloc
-      (abfd, sizeof (struct mips_elf_bfd2got_hash));
-
-    if (bfdgot == NULL)
-      return FALSE;
-
-    bfdgot->bfd = abfd;
-    bfdgot->g = g;
-    bfdgotp = htab_find_slot (gg->bfd2got, bfdgot, INSERT);
-
-    BFD_ASSERT (*bfdgotp == NULL);
-    *bfdgotp = bfdgot;
-  }
+  mips_elf_replace_bfd_got (abfd, g);
 
   /* Every symbol that is referenced in a dynamic relocation must be
      present in the primary GOT, so arrange for them to appear after
@@ -8879,7 +8790,7 @@ mips_elf_lay_out_got (bfd *output_bfd, struct bfd_link_info *info)
   struct mips_got_info *g;
   bfd_size_type loadable_size = 0;
   bfd_size_type page_gotno;
-  bfd *sub;
+  bfd *ibfd;
   struct mips_elf_traverse_got_arg tga;
   struct mips_elf_link_hash_table *htab;
 
@@ -8914,11 +8825,11 @@ mips_elf_lay_out_got (bfd *output_bfd, struct bfd_link_info *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)
+  for (ibfd = info->input_bfds; ibfd; ibfd = ibfd->link_next)
     {
       asection *subsection;
 
-      for (subsection = sub->sections;
+      for (subsection = ibfd->sections;
           subsection;
           subsection = subsection->next)
        {
@@ -8985,6 +8896,13 @@ mips_elf_lay_out_got (bfd *output_bfd, struct bfd_link_info *info)
     }
   else
     {
+      /* Record that all bfds use G.  This also has the effect of freeing
+        the per-bfd GOTs, which we no longer need.  */
+      for (ibfd = info->input_bfds; ibfd; ibfd = ibfd->link_next)
+       if (mips_elf_bfd_got (ibfd, FALSE))
+         mips_elf_replace_bfd_got (ibfd, g);
+      mips_elf_replace_bfd_got (output_bfd, g);
+
       /* Set up TLS entries.  */
       g->tls_assigned_gotno = g->global_gotno + g->local_gotno;
       tga.info = info;
@@ -10589,7 +10507,7 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd,
       BFD_ASSERT (sdyn != NULL);
       BFD_ASSERT (gg != NULL);
 
-      g = mips_elf_got_for_ibfd (gg, output_bfd);
+      g = mips_elf_bfd_got (output_bfd, FALSE);
       BFD_ASSERT (g != NULL);
 
       for (b = sdyn->contents;
index dc9eb82..bd7b94b 100644 (file)
@@ -1,5 +1,11 @@
 2013-02-11  Richard Sandiford  <rdsandiford@googlemail.com>
 
+       * ld-mips-elf/tls-hidden4.got, ld-mips-elf/tls-multi-got-1.d,
+       ld-mips-elf/tls-multi-got-1.got: Update for changes in the order
+       that symbols are added to per-bfd GOTs.
+
+2013-02-11  Richard Sandiford  <rdsandiford@googlemail.com>
+
        * ld-mips-elf/tls-hidden3.d, ld-mips-elf/tls-hidden3.got,
        ld-mips-elf/tls-multi-got-1.got, ld-mips-elf/tlsbin-o32.d,
        ld-mips-elf/tlsbin-o32.got, ld-mips-elf/tlsdyn-o32-1.d,
index e6b2115..7984501 100644 (file)
@@ -21,9 +21,9 @@ Contents of section \.got:
 # Likewise, but the order of the entries in this GOT is:
 #
 #     foo3
-#     foo2
 #     foo0
+#     foo2
 #     foo1
 #...
  1d0020 00000000 00000000 00000000 0000abcc  .*
- 1d0030 0000abc8 0000abc0 0000abc4           .*
+ 1d0030 0000abc0 0000abc8 0000abc4           .*
index 147dc83..937c269 100644 (file)
@@ -13,8 +13,8 @@ Disassembly of section .text:
 [0-9a-f]+ <sym_2_0000>:
 #...
 [0-9a-f]+ <tls_bits_2>:
-   [0-9a-f]+:  27841c64        addiu   a0,gp,7268
+   [0-9a-f]+:  27841c60        addiu   a0,gp,7264
    [0-9a-f]+:  27841c58        addiu   a0,gp,7256
-   [0-9a-f]+:  24441c60        addiu   a0,v0,7264
+   [0-9a-f]+:  24441c68        addiu   a0,v0,7272
    [0-9a-f]+:  00000000        nop
 #pass
index 6f666c1..95b56c2 100644 (file)
@@ -6,15 +6,15 @@ OFFSET   TYPE              VALUE
 00000000 R_MIPS_NONE       \*ABS\*
 0013f820 R_MIPS_TLS_DTPMOD32  \*ABS\*
 0014947c R_MIPS_TLS_DTPMOD32  \*ABS\*
-0013f82c R_MIPS_TLS_DTPMOD32  tlsvar_gd
-0013f830 R_MIPS_TLS_DTPREL32  tlsvar_gd
+0013f828 R_MIPS_TLS_DTPMOD32  tlsvar_gd
+0013f82c R_MIPS_TLS_DTPREL32  tlsvar_gd
 00149488 R_MIPS_TLS_DTPMOD32  tlsvar_gd
 0014948c R_MIPS_TLS_DTPREL32  tlsvar_gd
-0013f828 R_MIPS_TLS_TPREL32  tlsvar_ie
+0013f830 R_MIPS_TLS_TPREL32  tlsvar_ie
 00149484 R_MIPS_TLS_TPREL32  tlsvar_ie
-00143e3c R_MIPS_REL32      sym_1_9526
+00143ea8 R_MIPS_REL32      sym_1_9526
 #...
-0013a8f8 R_MIPS_REL32      sym_2_8654
+00139a84 R_MIPS_REL32      sym_2_8654
 
 
 Contents of section .got: