summaryrefslogtreecommitdiff
path: root/bfd/elfxx-sparc.c
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@gcc.gnu.org>2018-03-28 12:17:15 +0200
committerEric Botcazou <ebotcazou@gcc.gnu.org>2018-03-28 12:17:15 +0200
commitf8745e1cd139b5c6a5bd8a30ea84ccbd45dec81c (patch)
tree4898722dadeb8c77ef0a15c212cb061d8255edbe /bfd/elfxx-sparc.c
parentc8d59609b1cf66eaff3c486e483f5e3d647c66ff (diff)
downloadbinutils-gdb-f8745e1cd139b5c6a5bd8a30ea84ccbd45dec81c.tar.gz
PR ld/22972 on SPARC.
This is a regression for the corner case of a hidden symbol in a PIC/PIE binary which is subject to both a new-style GOTDATA relocation and an old-style GOT relocation. In this case, depending on the link order, the R_SPARC_RELATIVE dynamic relocation for the GOT slot needed because of the old-style relocation can be replaced with R_SPARC_NONE coming from the GOTDATA relocation. The fix simply records whether an old-style GOT relocation is seen for a symbol and prevents the R_SPARC_NONE from being generated in this case. bfd/ * elfxx-sparc.c (struct _bfd_sparc_elf_link_hash_entry): Add new flag has_old_style_got_reloc. (_bfd_sparc_elf_check_relocs) <GOT relocations>: Set it for old-style relocations. Fix a couple of long lines. (_bfd_sparc_elf_relocate_section) <R_SPARC_GOTDATA_OP>: Do not generate a R_SPARC_NONE for the GOT slot if the symbol is also subject to old-style GOT relocations. ld/ * testsuite/ld-sparc/sparc.exp: Add test for mixed GOTDATA/GOT relocs. * testsuite/ld-sparc/gotop-hidden.c: New file. * testsuite/ld-sparc/got-hidden32.s: Likewise. * testsuite/ld-sparc/got-hidden64.s: Likewise. * testsuite/ld-sparc/pass.out: Likewise.
Diffstat (limited to 'bfd/elfxx-sparc.c')
-rw-r--r--bfd/elfxx-sparc.c26
1 files changed, 19 insertions, 7 deletions
diff --git a/bfd/elfxx-sparc.c b/bfd/elfxx-sparc.c
index 849182fc8cc..81812afc5a4 100644
--- a/bfd/elfxx-sparc.c
+++ b/bfd/elfxx-sparc.c
@@ -701,9 +701,12 @@ struct _bfd_sparc_elf_link_hash_entry
#define GOT_TLS_IE 3
unsigned char tls_type;
- /* Symbol has GOT or PLT relocations. */
+ /* Symbol has GOT or PLT relocations. */
unsigned int has_got_reloc : 1;
+ /* Symbol has old-style, non-relaxable GOT relocations. */
+ unsigned int has_old_style_got_reloc : 1;
+
/* Symbol has non-GOT/non-PLT relocations in text sections. */
unsigned int has_non_got_reloc : 1;
@@ -1569,11 +1572,12 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
&& r_type != R_SPARC_GOTDATA_OP_LOX10)
local_got_refcounts[r_symndx] += 1;
- old_tls_type = _bfd_sparc_elf_local_got_tls_type (abfd) [r_symndx];
+ old_tls_type
+ = _bfd_sparc_elf_local_got_tls_type (abfd) [r_symndx];
}
- /* If a TLS symbol is accessed using IE at least once, there is no point
- in using the dynamic model for it. */
+ /* If a TLS symbol is accessed using IE at least once, there is no
+ point in using the dynamic model for it. */
if (old_tls_type != tls_type)
{
if (old_tls_type == GOT_UNKNOWN)
@@ -1603,7 +1607,13 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
return FALSE;
if (eh != NULL)
- eh->has_got_reloc = 1;
+ {
+ eh->has_got_reloc = 1;
+ if (r_type == R_SPARC_GOT10
+ || r_type == R_SPARC_GOT13
+ || r_type == R_SPARC_GOT22)
+ eh->has_old_style_got_reloc = 1;
+ }
break;
case R_SPARC_TLS_GD_CALL:
@@ -3138,12 +3148,14 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
bfd_put_32 (output_bfd, relocation, contents + rel->r_offset);
/* If the symbol is global but not dynamic, an .rela.* slot has
- been allocated for it in the GOT so output R_SPARC_NONE here.
- See also the handling of other GOT relocations just below. */
+ been allocated for it in the GOT so output R_SPARC_NONE here,
+ if it isn't also subject to another, old-style GOT relocation.
+ See also the handling of these GOT relocations just below. */
if (h != NULL
&& h->dynindx == -1
&& !h->forced_local
&& h->root.type != bfd_link_hash_undefweak
+ && !eh->has_old_style_got_reloc
&& (h->got.offset & 1) == 0
&& bfd_link_pic (info))
{