aboutsummaryrefslogtreecommitdiff
path: root/bfd/elfxx-sparc.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2017-01-02 22:06:28 +1030
committerAlan Modra <amodra@gmail.com>2017-01-02 22:06:28 +1030
commit5b86074c4a84e32ca55a6c72c5fca45d97dc9374 (patch)
treee3666b846d6e1cb9d942273723f901c6bf781e08 /bfd/elfxx-sparc.c
parent2571583aed598dd3f9651b53434e5f177a0e3cf7 (diff)
downloadfsf-binutils-gdb-5b86074c4a84e32ca55a6c72c5fca45d97dc9374.zip
fsf-binutils-gdb-5b86074c4a84e32ca55a6c72c5fca45d97dc9374.tar.gz
fsf-binutils-gdb-5b86074c4a84e32ca55a6c72c5fca45d97dc9374.tar.bz2
PR20989, sparc GOT sequence optimisation
PR ld/20989 * elfxx-sparc.c (gdop_relative_offset_ok): New function. (_bfd_sparc_elf_relocate_section): Use it to validate GOT indirect to GOT pointer relative code edit.
Diffstat (limited to 'bfd/elfxx-sparc.c')
-rw-r--r--bfd/elfxx-sparc.c31
1 files changed, 29 insertions, 2 deletions
diff --git a/bfd/elfxx-sparc.c b/bfd/elfxx-sparc.c
index 4ec013d..f66525e 100644
--- a/bfd/elfxx-sparc.c
+++ b/bfd/elfxx-sparc.c
@@ -2927,6 +2927,33 @@ gdopoff (struct bfd_link_info *info, bfd_vma address)
return address - got_base;
}
+/* Return whether H is local and its ADDRESS is within 4G of
+ _GLOBAL_OFFSET_TABLE_ and thus the offset may be calculated by a
+ sethi, xor sequence. */
+
+static bfd_boolean
+gdop_relative_offset_ok (struct bfd_link_info *info,
+ struct elf_link_hash_entry *h,
+ bfd_vma address ATTRIBUTE_UNUSED)
+{
+ if (!SYMBOL_REFERENCES_LOCAL (info, h))
+ return FALSE;
+ /* If H is undefined, ADDRESS will be zero. We can't allow a
+ relative offset to "zero" when producing PIEs or shared libs.
+ Note that to get here with an undefined symbol it must also be
+ hidden or internal visibility. */
+ if (bfd_link_pic (info)
+ && h != NULL
+ && (h->root.type == bfd_link_hash_undefweak
+ || h->root.type == bfd_link_hash_undefined))
+ return FALSE;
+#ifdef BFD64
+ return gdopoff (info, address) + ((bfd_vma) 1 << 32) < (bfd_vma) 2 << 32;
+#else
+ return TRUE;
+#endif
+}
+
/* Relocate a SPARC ELF section. */
bfd_boolean
@@ -3168,7 +3195,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
{
case R_SPARC_GOTDATA_OP_HIX22:
case R_SPARC_GOTDATA_OP_LOX10:
- if (SYMBOL_REFERENCES_LOCAL (info, h))
+ if (gdop_relative_offset_ok (info, h, relocation))
{
r_type = (r_type == R_SPARC_GOTDATA_OP_HIX22
? R_SPARC_GOTDATA_HIX22
@@ -3178,7 +3205,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
break;
case R_SPARC_GOTDATA_OP:
- if (SYMBOL_REFERENCES_LOCAL (info, h))
+ if (gdop_relative_offset_ok (info, h, relocation))
{
bfd_vma insn = bfd_get_32 (input_bfd, contents + rel->r_offset);