This is the mail archive of the
mailing list for the binutils project.
[PATCH] bfd: allow negative offsets to _GLOBAL_OFFSET_TABLE_ in elf64 SPARC
- From: jose dot marchesi at oracle dot com (Jose E. Marchesi)
- To: binutils at sourceware dot org
- Cc: David Miller <davem at davemloft dot net>, Eric Botcazou <ebotcazou at adacore dot com>
- Date: Tue, 13 Sep 2016 14:08:56 +0200
- Subject: [PATCH] bfd: allow negative offsets to _GLOBAL_OFFSET_TABLE_ in elf64 SPARC
- Authentication-results: sourceware.org; auth=none
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
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?
2016-09-12 Jose E. Marchesi <email@example.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
@@ -1,3 +1,9 @@
+2016-09-12 Jose E. Marchesi <firstname.lastname@example.org>
+ * 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 <email@example.com>
diff --git a/bfd/elfxx-sparc.c b/bfd/elfxx-sparc.c
index 63558c7..30daedf 100644
@@ -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;