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] bfd: allow negative offsets to _GLOBAL_OFFSET_TABLE_ in elf64 SPARC


The patch below enables the _GLOBAL_OFFSET_TABLE_ negative-offsets
optimization for 64-bit sparc targets.

This allows for bigger GOT tables (> 0x1000 bytes) addressable by a
signed 13-bits immediate, and therefore allows to use -fpic instead of
-fPIC in many cases, resulting in faster performance.

This also eases the porting of software from Solaris to GNU/Linux in
sparc machines, since it mimics the behavior of their linker's -Kpic and
-xcode=pic13 modes.

AFAIK the reason why the optimization was not enabled in sparc 64-bit
targets is because it used to break -fPIC, because the sethi/or pairs
used to load the 22-bit relocations don't support negative constants.
However, both GCC and the assembler were fixed to generate sethi/xor
pairs several years ago:

- binutils got support for gotdata relocations back in April 2008, in
  this commit from davem: 739f7f82beda72a2702c814d5a8af90a91b1c30d.

- GCC got support to generate sethi/xor pairs using %gdop relocations back
  in February 2010, in this commit from davem:
  2f1e7d0b3cc16bfdc2206528200cb3438c025c5e (gcc-git mirror).  In case the
  system assembler doesn't support gotdata relocations (checked at
  configure time) then GCC generates the old sethi/or pairs.

So, if there were not additional reasons to disable the optimization in
64-bit, it seems to me that enough time has passed since these patches
were applied to reasonably assume it is safe to activate the
optimization in sparc64 targets running the latest binutils.

In order to test this, first I manually inspected resolved relocations
when using -fpic and -fPIC in small test programs.  Then I ran the
master binutils testsuite and the master glibc testsuite (in both
sparcv9-linux-gnu and sparc64-linux-gnu targets) with no regressions.
All of this using trunk GCC.

Can you guys think on anything that may break due to this?
Otherwise, any objection to getting this pushed to binutils?

bfd/ChangeLog:
    
    2016-09-12  Jose E. Marchesi  <jose.marchesi@oracle.com>
    
    	* elfxx-sparc.c (_bfd_sparc_elf_size_dynamic_sections): Allow
    	negative offsets to _GLOBAL_OFFSET_TABLE_ if the .got section is
    	bigger than 0x1000 bytes.

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 56012b4..ae428d6 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,9 @@
+2016-09-12  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* elfxx-sparc.c (_bfd_sparc_elf_size_dynamic_sections): Allow
+	negative offsets to _GLOBAL_OFFSET_TABLE_ if the .got section is
+	bigger than 0x1000 bytes.
+
 2016-09-02  Senthil Kumar Selvaraj  <senthil_kumar.selvaraj@atmel.com>
 
 	PR ld/20545
diff --git a/bfd/elfxx-sparc.c b/bfd/elfxx-sparc.c
index 63558c7..30daedf 100644
--- a/bfd/elfxx-sparc.c
+++ b/bfd/elfxx-sparc.c
@@ -2661,19 +2661,19 @@ _bfd_sparc_elf_size_dynamic_sections (bfd *output_bfd,
   /* Allocate .plt and .got entries, and space for local symbols.  */
   htab_traverse (htab->loc_hash_table, allocate_local_dynrelocs, info);
 
-  if (! ABI_64_P (output_bfd)
-      && !htab->is_vxworks
+  if (!htab->is_vxworks
       && elf_hash_table (info)->dynamic_sections_created)
     {
-      /* Make space for the trailing nop in .plt.  */
-      if (htab->elf.splt->size > 0)
-	htab->elf.splt->size += 1 * SPARC_INSN_BYTES;
+      if (! ABI_64_P (output_bfd))
+        {
+          /* Make space for the trailing nop in .plt.  */
+          if (htab->elf.splt->size > 0)
+            htab->elf.splt->size += 1 * SPARC_INSN_BYTES;
+        }
 
       /* If the .got section is more than 0x1000 bytes, we add
 	 0x1000 to the value of _GLOBAL_OFFSET_TABLE_, so that 13
-	 bit relocations have a greater chance of working.
-
-	 FIXME: Make this optimization work for 64-bit too.  */
+	 bit relocations have a greater chance of working.  */
       if (htab->elf.sgot->size >= 0x1000
 	  && elf_hash_table (info)->hgot->root.u.def.value == 0)
 	elf_hash_table (info)->hgot->root.u.def.value = 0x1000;


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