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]

[PATCH 4/5] Improve handling of R_MIPS_32 GOT slots


The multigot code distinguishes between GOT entries that are used for
code references and those that are only used by dynamic relocations.
This patch introduces that distinction earlier and applies it to
objects that don't need multiple GOTs.

Specifically, if check_relocs sees a relocation against a global symbol
and if it thinks that relocation might survive as a dynamic relocation,
it forces the symbol to have a global GOT entry.  We don't know at this
stage if we're dealing with a dynamic link that uses a GOT, so we say
that the .got section can be excluded:

    if (! mips_elf_create_got_section (dynobj, info, TRUE))
      return FALSE;
    if (!mips_elf_record_global_got_symbol (h, abfd, info, 0))
      return FALSE;

This is the only case in which we pass TRUE to mips_elf_create_got_section.

We can do better if we just record that the global symbol's global_got_area
must be <= GGA_RELOC_ONLY.  We must then honour this when sorting the hash
table.

mips_elf_sort_hash_table currently only handles GGA_RELOC_ONLY for
multigots:

  hsd.max_unref_got_dynindx =
  hsd.min_got_dynindx = elf_hash_table (info)->dynsymcount
    /* In the multi-got case, assigned_gotno of the master got_info
       indicate the number of entries that aren't referenced in the
       primary GOT, but that must have entries because there are
       dynamic relocations that reference it.  Since they aren't
       referenced, we move them to the end of the GOT, so that they
       don't prevent other entries that are referenced from getting
       too large offsets.  */
    - (g->next ? g->assigned_gotno : 0);

(Here, assigned_gotno is the symbol index for the first GGA_RELOC_ONLY
symbol.)  The patch extends it to all cases by adding a new field,
"reloc_only_gotno", to the GOT structure.  The initialisation then
looks like this:

  hsd.max_unref_got_dynindx
    = hsd.min_got_dynindx
    = (elf_hash_table (info)->dynsymcount - g->reloc_only_gotno);

The patch has three advantages:

  - It can help avoid GOT overflow in cases that can't use a multigot
    (e.g. big ld -r output).

  - Before the patch, forced-local symbols that were referenced only
    by dynamic relocations would still get a GOT entry.  After the
    patch they don't.

    mips16-pic-2 is an example of this.

  - Suppose that a bfd B has a (possibly) dynamic R_MIPS_32 relocation
    against a global symbol S, and that the link needs multiple GOTs.
    Suppose also that B gets assigned a secondary GOT and that no bfds
    assigned to that secondary GOT use GOT relocations to refer to G.

    Before the patch, the secondary GOT would still have an unused entry
    for G (with an associated relocation to set up the GOT entry).
    After the patch it doesn't.

    tls-hidden4 is an example of this.

Tested on mips64-linux-gnu and mips64el-linux-gnu.  OK to install?

Richard


bfd/
	* elfxx-mips.c (mips_got_info): Add a "reloc_only_gotno" field.
	(mips_elf_got_section): Delete.
	(mips_elf_sort_hash_table): Use g->reloc_only_gotno to decide
	how many reloc-only entries there are.
	(mips_elf_count_got_symbols): Adjust g->reloc_only_gotno as
	well as g->global_gotno.
	(mips_elf_make_got_per_bfd): Initialize reloc_only_gotno.
	(mips_elf_multi_got): Likewise.  Use gg->reloc_only_gotno
	rather than gg->assigned_gotno to store the number of
	reloc-only GOT entries.
	(mips_elf_create_got_section): Remove the MAYBE_EXCLUDE parameter.
	Initialize reloc_only_gotno.
	(mips_elf_calculate_relocation): Check htab->got_info instead of
	dynobj when deciding whether to call mips_elf_adjust_gp,
	(_bfd_mips_elf_create_dynamic_sections): Adjust the call
	to mips_elf_create_got_section.
	(mips_elf_record_relocs): Likewise.  Remove redundant
	"dynobj == NULL" code.  Do not use mips_elf_create_got_section
	or mips_elf_record_global_got_symbol for R_MIPS_32, R_MIPS_REL32
	and R_MIPS_64; limit global_got_area to GGA_RELOC_ONLY instead.
	(_bfd_mips_elf_finish_dynamic_symbol): Use htab->sgot instead
	of mips_elf_got_section.
	(_bfd_mips_vxworks_finish_dynamic_symbol): Likewise.
	(_bfd_mips_elf_finish_dynamic_sections): Likewise.
	Move the initial assignment of G to the block that uses it;
	it is used for an unrelated purpose later.

ld/testsuite/
	* ld-mips-elf/tls-hidden4.got, ld-mips-elf/tls-hidden4.r: We have
	removed an unused GOT entry that was allocated for the R_MIPS_32
	relocation against "undef", so adjust addresses down by 4 bytes.
	* ld-mips-elf/got-dump-1.d, ld-mips-elf/got-dump-2.d: We have
	changed the order of the GOT entries so that reloc-only ones
	come last.  "undef" is only referred to by dynamic relocations,
	so it now comes after "glob".
	* ld-mips-elf/mips16-pic-2.dd, ld-mips-elf/mips16-pic-2.gd,
	ld-mips-elf/mips16-pic-2.nd, ld-mips-elf/mips16-pic-2.rd: We have
	removed two unused local GOT entries that were originally created
	as global entries for the hidden symbols "used2" and "used3".
	"used4" and "used5" are only referred to by relocations, so they
	now come after "used6" and "used7".

Index: bfd/elfxx-mips.c
===================================================================
--- bfd/elfxx-mips.c	2008-06-28 17:14:45.000000000 +0100
+++ bfd/elfxx-mips.c	2008-06-28 17:14:46.000000000 +0100
@@ -145,6 +145,8 @@ struct mips_got_info
   struct elf_link_hash_entry *global_gotsym;
   /* The number of global .got entries.  */
   unsigned int global_gotno;
+  /* The number of global .got entries that are in the GGA_RELOC_ONLY area.  */
+  unsigned int reloc_only_gotno;
   /* The number of .got slots used for TLS.  */
   unsigned int tls_gotno;
   /* The first unused TLS .got entry.  Used only during
@@ -2280,19 +2282,6 @@ mips_elf_rel_dyn_section (struct bfd_lin
   return sreloc;
 }
 
-/* Returns the GOT section, if it hasn't been excluded.  */
-
-static asection *
-mips_elf_got_section (struct bfd_link_info *info)
-{
-  struct mips_elf_link_hash_table *htab;
-
-  htab = mips_elf_hash_table (info);
-  if (htab->sgot == NULL || (htab->sgot->flags & SEC_EXCLUDE) != 0)
-    return NULL;
-  return htab->sgot;
-}
-
 /* Count the number of relocations needed for a TLS GOT entry, with
    access types from TLS_TYPE, and symbol H (or a local symbol if H
    is NULL).  */
@@ -2423,12 +2412,14 @@ mips_elf_initialize_tls_slots (bfd *abfd
 			       struct mips_elf_link_hash_entry *h,
 			       bfd_vma value)
 {
+  struct mips_elf_link_hash_table *htab;
   int indx;
   asection *sreloc, *sgot;
   bfd_vma offset, offset2;
   bfd_boolean need_relocs = FALSE;
 
-  sgot = mips_elf_got_section (info);
+  htab = mips_elf_hash_table (info);
+  sgot = htab->sgot;
 
   indx = 0;
   if (h != NULL)
@@ -2954,16 +2945,9 @@ mips_elf_sort_hash_table (bfd *abfd, str
     return TRUE;
 
   hsd.low = NULL;
-  hsd.max_unref_got_dynindx =
-  hsd.min_got_dynindx = elf_hash_table (info)->dynsymcount
-    /* In the multi-got case, assigned_gotno of the master got_info
-       indicate the number of entries that aren't referenced in the
-       primary GOT, but that must have entries because there are
-       dynamic relocations that reference it.  Since they aren't
-       referenced, we move them to the end of the GOT, so that they
-       don't prevent other entries that are referenced from getting
-       too large offsets.  */
-    - (g->next ? g->assigned_gotno : 0);
+  hsd.max_unref_got_dynindx
+    = hsd.min_got_dynindx
+    = (elf_hash_table (info)->dynsymcount - g->reloc_only_gotno);
   hsd.max_non_got_dynindx = count_section_dynsyms (abfd, info) + 1;
   mips_elf_link_hash_traverse (((struct mips_elf_link_hash_table *)
 				elf_hash_table (info)),
@@ -3413,7 +3397,11 @@ mips_elf_count_got_symbols (struct mips_
 	  h->global_got_area = GGA_NONE;
 	}
       else
-	g->global_gotno++;
+	{
+	  g->global_gotno++;
+	  if (h->global_got_area == GGA_RELOC_ONLY)
+	    g->reloc_only_gotno++;
+	}
     }
   return 1;
 }
@@ -3492,6 +3480,7 @@ mips_elf_get_got_for_bfd (struct htab *b
 
       g->global_gotsym = NULL;
       g->global_gotno = 0;
+      g->reloc_only_gotno = 0;
       g->local_gotno = 0;
       g->page_gotno = 0;
       g->assigned_gotno = -1;
@@ -3912,6 +3901,7 @@ mips_elf_multi_got (bfd *abfd, struct bf
 
       g->next->global_gotsym = NULL;
       g->next->global_gotno = 0;
+      g->next->reloc_only_gotno = 0;
       g->next->local_gotno = 0;
       g->next->page_gotno = 0;
       g->next->tls_gotno = 0;
@@ -3964,7 +3954,7 @@ mips_elf_multi_got (bfd *abfd, struct bf
   /* Every symbol that is referenced in a dynamic relocation must be
      present in the primary GOT, so arrange for them to appear after
      those that are actually referenced.  */
-  gg->assigned_gotno = gg->global_gotno - g->global_gotno;
+  gg->reloc_only_gotno = gg->global_gotno - g->global_gotno;
   g->global_gotno = gg->global_gotno;
 
   set_got_offset_arg.g = NULL;
@@ -4224,8 +4214,7 @@ mips_elf_highest (bfd_vma value ATTRIBUT
 /* Create the .got section to hold the global offset table.  */
 
 static bfd_boolean
-mips_elf_create_got_section (bfd *abfd, struct bfd_link_info *info,
-			     bfd_boolean maybe_exclude)
+mips_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
 {
   flagword flags;
   register asection *s;
@@ -4238,20 +4227,12 @@ mips_elf_create_got_section (bfd *abfd, 
   htab = mips_elf_hash_table (info);
 
   /* This function may be called more than once.  */
-  s = htab->sgot;
-  if (s)
-    {
-      if (! maybe_exclude)
-	s->flags &= ~SEC_EXCLUDE;
-      return TRUE;
-    }
+  if (htab->sgot)
+    return TRUE;
 
   flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
 	   | SEC_LINKER_CREATED);
 
-  if (maybe_exclude)
-    flags |= SEC_EXCLUDE;
-
   /* We have to use an alignment of 2**4 here because this is hardcoded
      in the function stub generation and in the linker script.  */
   s = bfd_make_section_with_flags (abfd, ".got", flags);
@@ -4285,6 +4266,7 @@ mips_elf_create_got_section (bfd *abfd, 
     return FALSE;
   g->global_gotsym = NULL;
   g->global_gotno = 0;
+  g->reloc_only_gotno = 0;
   g->tls_gotno = 0;
   g->local_gotno = MIPS_RESERVED_GOTNO (info);
   g->page_gotno = 0;
@@ -4642,7 +4624,7 @@ mips_elf_calculate_relocation (bfd *abfd
 
   gp0 = _bfd_get_gp_value (input_bfd);
   gp = _bfd_get_gp_value (abfd);
-  if (dynobj)
+  if (htab->got_info)
     gp += mips_elf_adjust_gp (abfd, htab->got_info, input_bfd);
 
   if (gnu_local_gp_p)
@@ -6417,7 +6399,7 @@ _bfd_mips_elf_create_dynamic_sections (b
     }
 
   /* We need to create .got section.  */
-  if (! mips_elf_create_got_section (abfd, info, FALSE))
+  if (!mips_elf_create_got_section (abfd, info))
     return FALSE;
 
   if (! mips_elf_rel_dyn_section (info, TRUE))
@@ -7043,7 +7025,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s
 	    case R_MIPS_TLS_LDM:
 	      if (dynobj == NULL)
 		elf_hash_table (info)->dynobj = dynobj = abfd;
-	      if (! mips_elf_create_got_section (dynobj, info, FALSE))
+	      if (!mips_elf_create_got_section (dynobj, info))
 		return FALSE;
 	      if (htab->is_vxworks && !info->shared)
 		{
@@ -7296,12 +7278,11 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s
 		 between global GOT entries and .dynsym entries.  */
 	      if (h != NULL && !htab->is_vxworks)
 		{
-		  if (dynobj == NULL)
-		    elf_hash_table (info)->dynobj = dynobj = abfd;
-		  if (! mips_elf_create_got_section (dynobj, info, TRUE))
-		    return FALSE;
-		  if (!mips_elf_record_global_got_symbol (h, abfd, info, 0))
-		    return FALSE;
+		  struct mips_elf_link_hash_entry *hmips;
+
+		  hmips = (struct mips_elf_link_hash_entry *) h;
+		  if (hmips->global_got_area > GGA_RELOC_ONLY)
+		    hmips->global_got_area = GGA_RELOC_ONLY;
 		}
 	    }
 
@@ -8759,8 +8740,7 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd
   BFD_ASSERT (h->dynindx != -1
 	      || h->forced_local);
 
-  sgot = mips_elf_got_section (info);
-  BFD_ASSERT (sgot != NULL);
+  sgot = htab->sgot;
   g = htab->got_info;
   BFD_ASSERT (g != NULL);
 
@@ -9032,8 +9012,7 @@ _bfd_mips_vxworks_finish_dynamic_symbol 
 
   BFD_ASSERT (h->dynindx != -1 || h->forced_local);
 
-  sgot = mips_elf_got_section (info);
-  BFD_ASSERT (sgot != NULL);
+  sgot = htab->sgot;
   g = htab->got_info;
   BFD_ASSERT (g != NULL);
 
@@ -9195,15 +9174,8 @@ _bfd_mips_elf_finish_dynamic_sections (b
 
   sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
 
-  sgot = mips_elf_got_section (info);
-  if (sgot == NULL)
-    gg = g = NULL;
-  else
-    {
-      gg = htab->got_info;
-      g = mips_elf_got_for_ibfd (gg, output_bfd);
-      BFD_ASSERT (g != NULL);
-    }
+  sgot = htab->sgot;
+  gg = htab->got_info;
 
   if (elf_hash_table (info)->dynamic_sections_created)
     {
@@ -9211,6 +9183,9 @@ _bfd_mips_elf_finish_dynamic_sections (b
       int dyn_to_skip = 0, dyn_skipped = 0;
 
       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;
Index: ld/testsuite/ld-mips-elf/tls-hidden4.got
===================================================================
--- ld/testsuite/ld-mips-elf/tls-hidden4.got	2008-06-28 17:09:10.000000000 +0100
+++ ld/testsuite/ld-mips-elf/tls-hidden4.got	2008-06-28 17:14:46.000000000 +0100
@@ -15,8 +15,8 @@ Contents of section \.got:
 # entry for each symbol.
 #
 #...
- 1c4010 00000000 00000000 0000abc8 0000abcc  .*
- 1c4020 0000abc0 0000abc4 00000000 80000000  .*
+ 1c4010 00000000 0000abc8 0000abcc 0000abc0  .*
+ 1c4020 0000abc4 00000000 80000000 00000000  .*
 #
 # Likewise, but the order of the entries in this GOT is:
 #
@@ -25,4 +25,5 @@ Contents of section \.got:
 #     foo0
 #     foo1
 #...
- 1d0030 0000abcc 0000abc8 0000abc0 0000abc4  .*
+ 1d0020 00000000 00000000 00000000 0000abcc  .*
+ 1d0030 0000abc8 0000abc0 0000abc4           .*
Index: ld/testsuite/ld-mips-elf/tls-hidden4.r
===================================================================
--- ld/testsuite/ld-mips-elf/tls-hidden4.r	2008-06-28 17:09:10.000000000 +0100
+++ ld/testsuite/ld-mips-elf/tls-hidden4.r	2008-06-28 17:14:46.000000000 +0100
@@ -7,13 +7,13 @@ Relocation section '\.rel\.dyn' at offse
 # important thing is that there is exactly one entry per GOT TLS slot
 # and that the addresses match those in the .got dump.
 #
+001c4014  0000002f R_MIPS_TLS_TPREL3
 001c4018  0000002f R_MIPS_TLS_TPREL3
 001c401c  0000002f R_MIPS_TLS_TPREL3
 001c4020  0000002f R_MIPS_TLS_TPREL3
-001c4024  0000002f R_MIPS_TLS_TPREL3
+001d002c  0000002f R_MIPS_TLS_TPREL3
 001d0030  0000002f R_MIPS_TLS_TPREL3
 001d0034  0000002f R_MIPS_TLS_TPREL3
 001d0038  0000002f R_MIPS_TLS_TPREL3
-001d003c  0000002f R_MIPS_TLS_TPREL3
 .* R_MIPS_REL32 .*
 #pass
Index: ld/testsuite/ld-mips-elf/got-dump-1.d
===================================================================
--- ld/testsuite/ld-mips-elf/got-dump-1.d	2008-06-28 17:09:10.000000000 +0100
+++ ld/testsuite/ld-mips-elf/got-dump-1.d	2008-06-28 17:14:46.000000000 +0100
@@ -20,6 +20,6 @@ Primary GOT:
  Global entries:
    Address     Access  Initial Sym.Val. Type    Ndx Name
   00060020 -32736\(gp\) 00050020 00050020 FUNC    UND extern
-  00060024 -32732\(gp\) 00000000 00000000 NOTYPE  UND undef
-  00060028 -32728\(gp\) 00050000 00050000 FUNC      7 glob
+  00060024 -32732\(gp\) 00050000 00050000 FUNC      7 glob
+  00060028 -32728\(gp\) 00000000 00000000 NOTYPE  UND undef
 
Index: ld/testsuite/ld-mips-elf/got-dump-2.d
===================================================================
--- ld/testsuite/ld-mips-elf/got-dump-2.d	2008-06-28 17:09:10.000000000 +0100
+++ ld/testsuite/ld-mips-elf/got-dump-2.d	2008-06-28 17:14:46.000000000 +0100
@@ -20,6 +20,6 @@ Primary GOT:
  Global entries:
            Address     Access          Initial         Sym.Val. Type    Ndx Name
   0001236000000030 -32720\(gp\) 0001235000000020 0001235000000020 FUNC    UND extern
-  0001236000000038 -32712\(gp\) 0000000000000000 0000000000000000 NOTYPE  UND undef
-  0001236000000040 -32704\(gp\) 0001235000000000 0001235000000000 FUNC      7 glob
+  0001236000000038 -32712\(gp\) 0001235000000000 0001235000000000 FUNC      7 glob
+  0001236000000040 -32704\(gp\) 0000000000000000 0000000000000000 NOTYPE  UND undef
 
Index: ld/testsuite/ld-mips-elf/mips16-pic-2.dd
===================================================================
--- ld/testsuite/ld-mips-elf/mips16-pic-2.dd	2008-06-28 17:14:18.000000000 +0100
+++ ld/testsuite/ld-mips-elf/mips16-pic-2.dd	2008-06-28 17:14:46.000000000 +0100
@@ -77,7 +77,7 @@ Disassembly of section \.text:
 .*:	[^\t]*	move	t9,v0
 .*:	[^\t]*	lw	v0,16\(sp\)
 .*:	[^\t]*	move	gp,v0
-.*:	[^\t]*	lw	v0,-32708\(v0\)
+.*:	[^\t]*	lw	v0,-32716\(v0\)
 .*:	[^\t]*	jalr	v0
 .*:	[^\t]*	move	t9,v0
 .*:	[^\t]*	lw	v0,16\(sp\)
@@ -101,7 +101,7 @@ Disassembly of section \.text:
 .*:	[^\t]*	move	t9,v0
 .*:	[^\t]*	lw	v0,16\(sp\)
 .*:	[^\t]*	move	gp,v0
-.*:	[^\t]*	lw	v0,-32696\(v0\)
+.*:	[^\t]*	lw	v0,-32712\(v0\)
 .*:	[^\t]*	jalr	v0
 .*:	[^\t]*	move	t9,v0
 .*:	[^\t]*	lw	v0,16\(sp\)
Index: ld/testsuite/ld-mips-elf/mips16-pic-2.gd
===================================================================
--- ld/testsuite/ld-mips-elf/mips16-pic-2.gd	2008-06-28 17:14:18.000000000 +0100
+++ ld/testsuite/ld-mips-elf/mips16-pic-2.gd	2008-06-28 17:14:46.000000000 +0100
@@ -16,13 +16,11 @@ Primary GOT:
   00050018 -32728\(gp\) 00000000
   0005001c -32724\(gp\) 00000000
   00050020 -32720\(gp\) 00000000
-  00050024 -32716\(gp\) 00000000
-  00050028 -32712\(gp\) 00000000
 
  Global entries:
    Address     Access  Initial Sym\.Val\. Type    Ndx Name
-  0005002c -32708\(gp\) 00040574 00040574 FUNC      6 used6
+  00050024 -32716\(gp\) 00040574 00040574 FUNC      6 used6
+  00050028 -32712\(gp\) 00040598 00040598 FUNC      6 used7
+  0005002c -32708\(gp\) 00040550 00040550 FUNC      6 used5
   00050030 -32704\(gp\) 0004052c 0004052c FUNC      6 used4
-  00050034 -32700\(gp\) 00040550 00040550 FUNC      6 used5
-  00050038 -32696\(gp\) 00040598 00040598 FUNC      6 used7
 
Index: ld/testsuite/ld-mips-elf/mips16-pic-2.nd
===================================================================
--- ld/testsuite/ld-mips-elf/mips16-pic-2.nd	2008-06-28 17:14:18.000000000 +0100
+++ ld/testsuite/ld-mips-elf/mips16-pic-2.nd	2008-06-28 17:14:46.000000000 +0100
@@ -3,8 +3,8 @@
      4: 000405bc    36 FUNC    GLOBAL DEFAULT .* used8
      5: .* _GLOBAL_OFFSET_TABLE_
      6: 00040574    36 FUNC    GLOBAL DEFAULT .* used6
-     7: 0004052c    36 FUNC    GLOBAL DEFAULT .* used4
+     7: 00040598    36 FUNC    GLOBAL DEFAULT .* used7
      8: 00040550    36 FUNC    GLOBAL DEFAULT .* used5
-     9: 00040598    36 FUNC    GLOBAL DEFAULT .* used7
+     9: 0004052c    36 FUNC    GLOBAL DEFAULT .* used4
 
 #pass
Index: ld/testsuite/ld-mips-elf/mips16-pic-2.rd
===================================================================
--- ld/testsuite/ld-mips-elf/mips16-pic-2.rd	2008-06-28 17:14:18.000000000 +0100
+++ ld/testsuite/ld-mips-elf/mips16-pic-2.rd	2008-06-28 17:14:46.000000000 +0100
@@ -5,5 +5,5 @@ Relocation section '\.rel\.dyn' .*:
 0+50400 * [0-9]+ * R_MIPS_REL32 *
 0+50404 * [0-9]+ * R_MIPS_REL32 *
 0+50410 * [0-9]+ * R_MIPS_REL32 *
-0+50408 * [0-9]+ * R_MIPS_REL32 * 0004052c * used4
 0+50414 * [0-9]+ * R_MIPS_REL32 * 00040550 * used5
+0+50408 * [0-9]+ * R_MIPS_REL32 * 0004052c * used4


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