diff options
author | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2018-03-28 12:17:15 +0200 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2018-03-28 12:17:15 +0200 |
commit | f8745e1cd139b5c6a5bd8a30ea84ccbd45dec81c (patch) | |
tree | 4898722dadeb8c77ef0a15c212cb061d8255edbe /bfd | |
parent | c8d59609b1cf66eaff3c486e483f5e3d647c66ff (diff) | |
download | gdb-f8745e1cd139b5c6a5bd8a30ea84ccbd45dec81c.zip gdb-f8745e1cd139b5c6a5bd8a30ea84ccbd45dec81c.tar.gz gdb-f8745e1cd139b5c6a5bd8a30ea84ccbd45dec81c.tar.bz2 |
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')
-rw-r--r-- | bfd/ChangeLog | 11 | ||||
-rw-r--r-- | bfd/elfxx-sparc.c | 26 |
2 files changed, 30 insertions, 7 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 426561a..dd6ccab 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,14 @@ +2018-03-28 Eric Botcazou <ebotcazou@adacore.com> + + PR ld/22972 + * 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. + 2018-03-25 H.J. Lu <hongjiu.lu@intel.com> PR ld/23000 diff --git a/bfd/elfxx-sparc.c b/bfd/elfxx-sparc.c index 849182f..81812af 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)) { |