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 /ld/testsuite | |
parent | c8d59609b1cf66eaff3c486e483f5e3d647c66ff (diff) | |
download | fsf-binutils-gdb-f8745e1cd139b5c6a5bd8a30ea84ccbd45dec81c.zip fsf-binutils-gdb-f8745e1cd139b5c6a5bd8a30ea84ccbd45dec81c.tar.gz fsf-binutils-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 'ld/testsuite')
-rw-r--r-- | ld/testsuite/ld-sparc/got-hidden32.s | 18 | ||||
-rw-r--r-- | ld/testsuite/ld-sparc/got-hidden64.s | 18 | ||||
-rw-r--r-- | ld/testsuite/ld-sparc/gotop-hidden.c | 13 | ||||
-rw-r--r-- | ld/testsuite/ld-sparc/pass.out | 1 | ||||
-rw-r--r-- | ld/testsuite/ld-sparc/sparc.exp | 29 |
5 files changed, 79 insertions, 0 deletions
diff --git a/ld/testsuite/ld-sparc/got-hidden32.s b/ld/testsuite/ld-sparc/got-hidden32.s new file mode 100644 index 0000000..cd1ecf2 --- /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 0000000..50e75ca --- /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 0000000..d769c6d --- /dev/null +++ b/ld/testsuite/ld-sparc/gotop-hidden.c @@ -0,0 +1,13 @@ +#include <stdio.h> + +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 0000000..7ef22e9 --- /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 e8aa0c2..41aa2e6 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" \ + ] \ + ] +} |