diff options
author | Alan Modra <amodra@gmail.com> | 2017-01-02 22:06:28 +1030 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2017-01-02 22:06:28 +1030 |
commit | 5b86074c4a84e32ca55a6c72c5fca45d97dc9374 (patch) | |
tree | e3666b846d6e1cb9d942273723f901c6bf781e08 /bfd/elfxx-sparc.c | |
parent | 2571583aed598dd3f9651b53434e5f177a0e3cf7 (diff) | |
download | gdb-5b86074c4a84e32ca55a6c72c5fca45d97dc9374.zip gdb-5b86074c4a84e32ca55a6c72c5fca45d97dc9374.tar.gz 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.c | 31 |
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); |