This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[14/20] MIPS GOT: Remove bfd2got code


This patch makes the multigot code use the per-BFD got information added
by the previous patch, rather than recreate per-BFD information from the
master GOT.

Richard

bfd/
	* 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.

Index: bfd/elfxx-mips.c
===================================================================
*** bfd/elfxx-mips.c	2013-02-11 16:41:59.394083455 +0000
--- bfd/elfxx-mips.c	2013-02-11 16:42:19.907206346 +0000
*************** struct mips_got_info
*** 161,169 ****
    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;
--- 161,166 ----
*************** struct mips_got_info
*** 174,194 ****
    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.  */
  
  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.  */
--- 171,180 ----
    bfd_vma tls_ldm_offset;
  };
  
! /* Structure passed when merging bfds' gots.  */
  
  struct mips_elf_got_per_bfd_arg
  {
    /* The output bfd.  */
    bfd *obfd;
    /* The link information.  */
*************** #define rpdNil ((pRPDR) 0)
*** 696,703 ****
     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;
--- 682,687 ----
*************** mips_elf_bfd_got (bfd *abfd, bfd_boolean
*** 2903,2908 ****
--- 2887,2911 ----
    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.  */
*************** mips_elf_count_got_entry (struct bfd_lin
*** 3036,3041 ****
--- 3039,3061 ----
      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.  */
*************** mips_elf_global_got_index (bfd *abfd, bf
*** 3365,3377 ****
    BFD_ASSERT (htab != NULL);
  
    gg = g = htab->got_info;
!   if (g->bfd2got && ibfd)
      {
        struct mips_got_entry e, *p;
  
        BFD_ASSERT (h->dynindx >= 0);
  
!       g = mips_elf_got_for_ibfd (g, ibfd);
        if (g->next != gg || TLS_RELOC_P (r_type))
  	{
  	  e.abfd = ibfd;
--- 3385,3398 ----
    BFD_ASSERT (htab != NULL);
  
    gg = g = htab->got_info;
!   if (g->next && ibfd)
      {
        struct mips_got_entry e, *p;
  
        BFD_ASSERT (h->dynindx >= 0);
  
!       g = mips_elf_bfd_got (ibfd, FALSE);
!       BFD_ASSERT (g);
        if (g->next != gg || TLS_RELOC_P (r_type))
  	{
  	  e.abfd = ibfd;
*************** mips_elf_create_local_got_entry (bfd *ab
*** 3535,3544 ****
    entry.d.address = value;
    entry.tls_type = mips_elf_reloc_tls_type (r_type);
  
!   g = mips_elf_got_for_ibfd (htab->got_info, ibfd);
    if (g == NULL)
      {
!       g = mips_elf_got_for_ibfd (htab->got_info, abfd);
        BFD_ASSERT (g != NULL);
      }
  
--- 3556,3565 ----
    entry.d.address = value;
    entry.tls_type = mips_elf_reloc_tls_type (r_type);
  
!   g = mips_elf_bfd_got (ibfd, FALSE);
    if (g == NULL)
      {
!       g = mips_elf_bfd_got (abfd, FALSE);
        BFD_ASSERT (g != NULL);
      }
  
*************** mips_elf_count_got_symbols (struct mips_
*** 4163,4309 ****
    return 1;
  }
  
! /* 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.  */
  
  static int
! mips_elf_bfd2got_entry_eq (const void *entry1, const void *entry2)
! {
!   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;
  
!   if (bfdgot == NULL)
      {
!       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;
      }
! 
!   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)
      {
!       arg->obfd = NULL;
!       return 0;
      }
- 
-   /* 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.  */
  
  static int
! mips_elf_make_got_pages_per_bfd (void **entryp, void *p)
  {
!   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;
  
!   g = mips_elf_get_got_for_bfd (arg->bfd2got, arg->obfd, entry->abfd);
!   if (g == NULL)
      {
!       arg->obfd = 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;
    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.)  */
  
  static int
! mips_elf_merge_got_with (struct mips_elf_bfd2got_hash *bfd2got,
  			 struct mips_got_info *to,
  			 struct mips_elf_got_per_bfd_arg *arg)
  {
!   struct mips_got_info *from = bfd2got->g;
    unsigned int estimate;
  
    /* Work out how many page entries we would need for the combined GOT.  */
--- 4184,4253 ----
    return 1;
  }
  
! /* 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_add_got_entry (void **entryp, void *data)
  {
!   struct mips_got_entry *entry;
!   struct mips_elf_traverse_got_arg *arg;
!   void **slot;
  
!   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)
      {
!       arg->g = NULL;
!       return 0;
      }
!   if (!*slot)
      {
!       *slot = entry;
!       mips_elf_count_got_entry (arg->info, arg->g, entry);
      }
    return 1;
  }
  
! /* 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_add_got_page_entry (void **entryp, void *data)
  {
!   struct mips_got_page_entry *entry;
!   struct mips_elf_traverse_got_arg *arg;
!   void **slot;
  
!   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->g = NULL;
        return 0;
      }
!   if (!*slot)
!     {
!       *slot = entry;
!       arg->g->page_gotno += entry->num_pages;
!     }
    return 1;
  }
  
! /* 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 (bfd *abfd, struct mips_got_info *from,
  			 struct mips_got_info *to,
  			 struct mips_elf_got_per_bfd_arg *arg)
  {
!   struct mips_elf_traverse_got_arg tga;
    unsigned int estimate;
  
    /* Work out how many page entries we would need for the combined GOT.  */
*************** mips_elf_merge_got_with (struct mips_elf
*** 4328,4371 ****
    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)
      return 0;
  
!   htab_traverse (from->got_page_entries, mips_elf_make_got_pages_per_bfd, arg);
!   if (arg->obfd == NULL)
      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);
    return 1;
  }
  
! /* Attempt to merge gots of different input bfds.  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)
  {
!   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;
    unsigned int estimate;
    int result;
  
!   g = bfd2got->g;
  
    /* Work out the number of page, local and TLS entries.  */
    estimate = arg->max_pages;
--- 4272,4313 ----
    if (estimate > arg->max_count)
      return -1;
  
    /* Transfer the bfd's got information from FROM to TO.  */
!   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_add_got_page_entry, &tga);
!   if (!tga.g)
      return 0;
  
!   mips_elf_replace_bfd_got (abfd, to);
    return 1;
  }
  
! /* 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 bfd_boolean
! mips_elf_merge_got (bfd *abfd, struct mips_got_info *g,
! 		    struct mips_elf_got_per_bfd_arg *arg)
  {
!   struct mips_elf_traverse_got_arg tga;
    unsigned int estimate;
    int result;
  
!   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;
*************** mips_elf_merge_gots (void **bfd2got_, vo
*** 4385,4396 ****
  	 a starting point for the primary GOT.  */
        if (!arg->primary)
  	{
! 	  arg->primary = bfd2got->g;
! 	  return 1;
  	}
  
        /* Try merging with the primary GOT.  */
!       result = mips_elf_merge_got_with (bfd2got, arg->primary, arg);
        if (result >= 0)
  	return result;
      }
--- 4327,4338 ----
  	 a starting point for the primary GOT.  */
        if (!arg->primary)
  	{
! 	  arg->primary = g;
! 	  return TRUE;
  	}
  
        /* Try merging with the primary GOT.  */
!       result = mips_elf_merge_got_with (abfd, g, arg->primary, arg);
        if (result >= 0)
  	return result;
      }
*************** mips_elf_merge_gots (void **bfd2got_, vo
*** 4398,4404 ****
    /* If we can merge with the last-created got, do it.  */
    if (arg->current)
      {
!       result = mips_elf_merge_got_with (bfd2got, arg->current, arg);
        if (result >= 0)
  	return result;
      }
--- 4340,4346 ----
    /* If we can merge with the last-created got, do it.  */
    if (arg->current)
      {
!       result = mips_elf_merge_got_with (abfd, g, arg->current, arg);
        if (result >= 0)
  	return result;
      }
*************** mips_elf_merge_gots (void **bfd2got_, vo
*** 4409,4415 ****
    g->next = arg->current;
    arg->current = g;
  
!   return 1;
  }
  
  /* ENTRYP is a hash table entry for a mips_got_entry.  Set its gotidx
--- 4351,4357 ----
    g->next = arg->current;
    arg->current = g;
  
!   return TRUE;
  }
  
  /* ENTRYP is a hash table entry for a mips_got_entry.  Set its gotidx
*************** mips_elf_forbid_lazy_stubs (void **entry
*** 4592,4601 ****
  static bfd_vma
  mips_elf_adjust_gp (bfd *abfd, struct mips_got_info *g, bfd *ibfd)
  {
!   if (g->bfd2got == NULL)
      return 0;
  
!   g = mips_elf_got_for_ibfd (g, ibfd);
    if (! g)
      return 0;
  
--- 4534,4543 ----
  static bfd_vma
  mips_elf_adjust_gp (bfd *abfd, struct mips_got_info *g, bfd *ibfd)
  {
!   if (!g->next)
      return 0;
  
!   g = mips_elf_bfd_got (ibfd, FALSE);
    if (! g)
      return 0;
  
*************** mips_elf_multi_got (bfd *abfd, struct bf
*** 4619,4652 ****
    struct mips_elf_traverse_got_arg tga;
    struct mips_got_info *g, *gg;
    unsigned int assign, needed_relocs;
!   bfd *dynobj;
  
    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)
--- 4561,4576 ----
    struct mips_elf_traverse_got_arg tga;
    struct mips_got_info *g, *gg;
    unsigned int assign, needed_relocs;
!   bfd *dynobj, *ibfd;
  
    dynobj = elf_hash_table (info)->dynobj;
    htab = mips_elf_hash_table (info);
    BFD_ASSERT (htab != NULL);
  
    g = htab->got_info;
  
    got_per_bfd_arg.obfd = abfd;
    got_per_bfd_arg.info = info;
    got_per_bfd_arg.current = NULL;
    got_per_bfd_arg.primary = NULL;
    got_per_bfd_arg.max_count = ((MIPS_ELF_GOT_MAX_SIZE (info)
*************** mips_elf_multi_got (bfd *abfd, struct bf
*** 4661,4669 ****
    /* 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;
  
    /* If we do not find any suitable primary GOT, create an empty one.  */
    if (got_per_bfd_arg.primary == NULL)
--- 4585,4596 ----
    /* 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.  */
!   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)
*************** mips_elf_multi_got (bfd *abfd, struct bf
*** 4681,4703 ****
       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;
!   }
  
    /* Every symbol that is referenced in a dynamic relocation must be
       present in the primary GOT, so arrange for them to appear after
--- 4608,4614 ----
       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.  */
!   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
*************** mips_elf_lay_out_got (bfd *output_bfd, s
*** 8879,8885 ****
    struct mips_got_info *g;
    bfd_size_type loadable_size = 0;
    bfd_size_type page_gotno;
!   bfd *sub;
    struct mips_elf_traverse_got_arg tga;
    struct mips_elf_link_hash_table *htab;
  
--- 8790,8796 ----
    struct mips_got_info *g;
    bfd_size_type loadable_size = 0;
    bfd_size_type page_gotno;
!   bfd *ibfd;
    struct mips_elf_traverse_got_arg tga;
    struct mips_elf_link_hash_table *htab;
  
*************** mips_elf_lay_out_got (bfd *output_bfd, s
*** 8914,8924 ****
    /* 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;
  
!       for (subsection = sub->sections;
  	   subsection;
  	   subsection = subsection->next)
  	{
--- 8825,8835 ----
    /* Calculate the total loadable size of the output.  That
       will give us the maximum number of GOT_PAGE entries
       required.  */
!   for (ibfd = info->input_bfds; ibfd; ibfd = ibfd->link_next)
      {
        asection *subsection;
  
!       for (subsection = ibfd->sections;
  	   subsection;
  	   subsection = subsection->next)
  	{
*************** mips_elf_lay_out_got (bfd *output_bfd, s
*** 8985,8990 ****
--- 8896,8908 ----
      }
    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;
*************** _bfd_mips_elf_finish_dynamic_sections (b
*** 10589,10595 ****
        BFD_ASSERT (sdyn != NULL);
        BFD_ASSERT (gg != NULL);
  
!       g = mips_elf_got_for_ibfd (gg, output_bfd);
        BFD_ASSERT (g != NULL);
  
        for (b = sdyn->contents;
--- 10507,10513 ----
        BFD_ASSERT (sdyn != NULL);
        BFD_ASSERT (gg != NULL);
  
!       g = mips_elf_bfd_got (output_bfd, FALSE);
        BFD_ASSERT (g != NULL);
  
        for (b = sdyn->contents;
Index: ld/testsuite/ld-mips-elf/tls-hidden4.got
===================================================================
*** ld/testsuite/ld-mips-elf/tls-hidden4.got	2013-02-11 16:41:19.845848082 +0000
--- ld/testsuite/ld-mips-elf/tls-hidden4.got	2013-02-11 16:42:00.242088508 +0000
*************** Contents of section \.got:
*** 21,29 ****
  # Likewise, but the order of the entries in this GOT is:
  #
  #     foo3
- #     foo2
  #     foo0
  #     foo1
  #...
   1d0020 00000000 00000000 00000000 0000abcc  .*
!  1d0030 0000abc8 0000abc0 0000abc4           .*
--- 21,29 ----
  # Likewise, but the order of the entries in this GOT is:
  #
  #     foo3
  #     foo0
+ #     foo2
  #     foo1
  #...
   1d0020 00000000 00000000 00000000 0000abcc  .*
!  1d0030 0000abc0 0000abc8 0000abc4           .*
Index: ld/testsuite/ld-mips-elf/tls-multi-got-1.d
===================================================================
*** ld/testsuite/ld-mips-elf/tls-multi-got-1.d	2013-02-11 16:41:19.845848082 +0000
--- ld/testsuite/ld-mips-elf/tls-multi-got-1.d	2013-02-11 16:42:00.242088508 +0000
*************** Disassembly of section .text:
*** 13,20 ****
  [0-9a-f]+ <sym_2_0000>:
  #...
  [0-9a-f]+ <tls_bits_2>:
!    [0-9a-f]+:	27841c64 	addiu	a0,gp,7268
     [0-9a-f]+:	27841c58 	addiu	a0,gp,7256
!    [0-9a-f]+:	24441c60 	addiu	a0,v0,7264
     [0-9a-f]+:	00000000 	nop
  #pass
--- 13,20 ----
  [0-9a-f]+ <sym_2_0000>:
  #...
  [0-9a-f]+ <tls_bits_2>:
!    [0-9a-f]+:	27841c60 	addiu	a0,gp,7264
     [0-9a-f]+:	27841c58 	addiu	a0,gp,7256
!    [0-9a-f]+:	24441c68 	addiu	a0,v0,7272
     [0-9a-f]+:	00000000 	nop
  #pass
Index: ld/testsuite/ld-mips-elf/tls-multi-got-1.got
===================================================================
*** ld/testsuite/ld-mips-elf/tls-multi-got-1.got	2013-02-11 16:41:19.844848076 +0000
--- ld/testsuite/ld-mips-elf/tls-multi-got-1.got	2013-02-11 16:42:00.243088514 +0000
*************** OFFSET   TYPE              VALUE
*** 6,20 ****
  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
  00149488 R_MIPS_TLS_DTPMOD32  tlsvar_gd
  0014948c R_MIPS_TLS_DTPREL32  tlsvar_gd
! 0013f828 R_MIPS_TLS_TPREL32  tlsvar_ie
  00149484 R_MIPS_TLS_TPREL32  tlsvar_ie
! 00143e3c R_MIPS_REL32      sym_1_9526
  #...
! 0013a8f8 R_MIPS_REL32      sym_2_8654
  
  
  Contents of section .got:
--- 6,20 ----
  00000000 R_MIPS_NONE       \*ABS\*
  0013f820 R_MIPS_TLS_DTPMOD32  \*ABS\*
  0014947c R_MIPS_TLS_DTPMOD32  \*ABS\*
! 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
! 0013f830 R_MIPS_TLS_TPREL32  tlsvar_ie
  00149484 R_MIPS_TLS_TPREL32  tlsvar_ie
! 00143ea8 R_MIPS_REL32      sym_1_9526
  #...
! 00139a84 R_MIPS_REL32      sym_2_8654
  
  
  Contents of section .got:


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]