From f8745e1cd139b5c6a5bd8a30ea84ccbd45dec81c Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Wed, 28 Mar 2018 12:17:15 +0200 Subject: [PATCH] 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) : Set it for old-style relocations. Fix a couple of long lines. (_bfd_sparc_elf_relocate_section) : 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. --- bfd/ChangeLog | 11 +++++++++++ bfd/elfxx-sparc.c | 26 ++++++++++++++++++------- ld/ChangeLog | 9 +++++++++ ld/testsuite/ld-sparc/got-hidden32.s | 18 +++++++++++++++++ ld/testsuite/ld-sparc/got-hidden64.s | 18 +++++++++++++++++ ld/testsuite/ld-sparc/gotop-hidden.c | 13 +++++++++++++ ld/testsuite/ld-sparc/pass.out | 1 + ld/testsuite/ld-sparc/sparc.exp | 29 ++++++++++++++++++++++++++++ 8 files changed, 118 insertions(+), 7 deletions(-) create mode 100644 ld/testsuite/ld-sparc/got-hidden32.s create mode 100644 ld/testsuite/ld-sparc/got-hidden64.s create mode 100644 ld/testsuite/ld-sparc/gotop-hidden.c create mode 100644 ld/testsuite/ld-sparc/pass.out diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 426561a00eb..dd6ccabea34 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,14 @@ +2018-03-28 Eric Botcazou + + 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) : Set it for old-style + relocations. Fix a couple of long lines. + (_bfd_sparc_elf_relocate_section) : 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 PR ld/23000 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)) { diff --git a/ld/ChangeLog b/ld/ChangeLog index dfdc648fc65..5f348191b45 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,12 @@ +2018-03-28 Eric Botcazou + + PR ld/22972 + * 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. + 2018-03-25 H.J. Lu PR ld/23000 diff --git a/ld/testsuite/ld-sparc/got-hidden32.s b/ld/testsuite/ld-sparc/got-hidden32.s new file mode 100644 index 00000000000..cd1ecf2d947 --- /dev/null +++ b/ld/testsuite/ld-sparc/got-hidden32.s @@ -0,0 +1,18 @@ + .text +.LLGETPC0: + retl + add %o7, %l7, %l7 + .global foo + .type foo, #function + .proc 04 +foo: + save %sp, -104, %sp + sethi %hi(_GLOBAL_OFFSET_TABLE_-4), %l7 + call .LLGETPC0 + add %l7, %lo(_GLOBAL_OFFSET_TABLE_+4), %l7 + sethi %hi(var), %g1 + or %g1, %lo(var), %g1 + ld [%l7+%g1], %g1 + ld [%g1], %i0 + ret + restore diff --git a/ld/testsuite/ld-sparc/got-hidden64.s b/ld/testsuite/ld-sparc/got-hidden64.s new file mode 100644 index 00000000000..50e75ca4525 --- /dev/null +++ b/ld/testsuite/ld-sparc/got-hidden64.s @@ -0,0 +1,18 @@ + .text +.LLGETPC0: + retl + add %o7, %l7, %l7 + .global foo + .type foo, #function + .proc 04 +foo: + save %sp, -160, %sp + sethi %hi(_GLOBAL_OFFSET_TABLE_-4), %l7 + call .LLGETPC0 + add %l7, %lo(_GLOBAL_OFFSET_TABLE_+4), %l7 + sethi %hi(var), %g1 + or %g1, %lo(var), %g1 + ldx [%l7+%g1], %g1 + ld [%g1], %i0 + ret + restore diff --git a/ld/testsuite/ld-sparc/gotop-hidden.c b/ld/testsuite/ld-sparc/gotop-hidden.c new file mode 100644 index 00000000000..d769c6ddc66 --- /dev/null +++ b/ld/testsuite/ld-sparc/gotop-hidden.c @@ -0,0 +1,13 @@ +#include + +extern unsigned int foo (void); + +__attribute__((visibility("hidden"))) unsigned int var = 0xdeadbeef; + +int main (void) +{ + if (var == foo ()) + puts ("PASS"); + + return 0; +} diff --git a/ld/testsuite/ld-sparc/pass.out b/ld/testsuite/ld-sparc/pass.out new file mode 100644 index 00000000000..7ef22e9a431 --- /dev/null +++ b/ld/testsuite/ld-sparc/pass.out @@ -0,0 +1 @@ +PASS diff --git a/ld/testsuite/ld-sparc/sparc.exp b/ld/testsuite/ld-sparc/sparc.exp index e8aa0c284c1..41aa2e68b2e 100644 --- a/ld/testsuite/ld-sparc/sparc.exp +++ b/ld/testsuite/ld-sparc/sparc.exp @@ -146,8 +146,37 @@ set sparc64tests { if { ![istarget "sparc64-*-elf*"] } { run_ld_link_tests $sparctests } + if { !([istarget "sparc-*-elf*"] || [istarget "sparc-sun-solaris2.5*"] || [istarget "sparc-sun-solaris2.6"]) } { run_ld_link_tests $sparc64tests } + +if { [istarget "sparc*-*-linux*"] && [isnative] } { + run_ld_link_exec_tests [list \ + [list \ + "32-bit: mixed GOTDATA/GOT relocations" \ + "-pie -m32" \ + "" \ + { gotop-hidden.c got-hidden32.s } \ + "gotop-hidden32" \ + "pass.out" \ + "-fPIE -m32" \ + ] \ + ] +} + +if { [istarget "sparc64-*-linux*"] && [isnative] } { + run_ld_link_exec_tests [list \ + [list \ + "64-bit: mixed GOTDATA/GOT relocations" \ + "-pie -m64" \ + "" \ + { gotop-hidden.c got-hidden64.s } \ + "gotop-hidden64" \ + "pass.out" \ + "-fPIE -m64" \ + ] \ + ] +} -- 2.30.2