aboutsummaryrefslogtreecommitdiff
path: root/bfd/elfxx-sparc.c
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@gcc.gnu.org>2018-01-25 12:16:06 +0100
committerEric Botcazou <ebotcazou@gcc.gnu.org>2018-01-25 12:16:06 +0100
commitbb363086e7743506d78bc6b1e56face0fb1fc93f (patch)
tree727ee3a49b87274a9c621005a7f24350edff9dba /bfd/elfxx-sparc.c
parent3e53a58e1f557f9b799506b62ac1cbf456b34647 (diff)
downloadgdb-bb363086e7743506d78bc6b1e56face0fb1fc93f.zip
gdb-bb363086e7743506d78bc6b1e56face0fb1fc93f.tar.gz
gdb-bb363086e7743506d78bc6b1e56face0fb1fc93f.tar.bz2
Fix PR ld/22727 (TLS breakage in PIC/PIE mode on SPARC).
There are actually 2 different bugs: 1. TLS transition is broken in PIE mode. 2. TLS is broken in PIC/PIE mode when the __tls_get_addr symbol is versioned (as is the case on Linux and Solaris at least). The 1st bug is fixed by reverting the problematic change for now (note that the associated test doesn't pass on SPARC because of another issue so there is no formal regression in the testsuite). The 2nd bug is fixed by changing the call to _bfd_generic_link_add_one_symbol on __tls_get_addr into a mere lookup in _bfd_sparc_elf_check_relocs. bfd/ * elfxx-sparc.c (_bfd_sparc_elf_check_relocs) <R_SPARC_TLS_GD_CALL>: Do a mere lookup of the __tls_get_addr symbol instead of adding it. Revert 2017-10-19 H.J. Lu <hongjiu.lu@intel.com> PR ld/22263 * elfxx-sparc.c (sparc_elf_tls_transition): Replace bfd_link_pic with !bfd_link_executable, !bfd_link_pic with bfd_link_executable for TLS check. (_bfd_sparc_elf_check_relocs): Likewise. (allocate_dynrelocs): Likewise. (_bfd_sparc_elf_relocate_section): Likewise. ld/ * testsuite/ld-sparc/sparc.exp (32-bit: Helper shared library): Link with a version script. (32-bit: TLS -fpie): New test. (64-bit: Helper shared library): Link with a version script. (64-bit: TLS -fpie): New test. (64-bit: GOTDATA relocations): Pass -Av9 to the assembler. * testsuite/ld-sparc/tlslib.ver: New file. * testsuite/ld-sparc/tlspie32.dd: Likewise. * testsuite/ld-sparc/tlspie32.s: Likewise. * testsuite/ld-sparc/tlspie64.dd: Likewise. * testsuite/ld-sparc/tlspie64.s: Likewise. * testsuite/ld-sparc/tlssunbin32.dd: Adjust for versioned symbol. * testsuite/ld-sparc/tlssunbin32.rd: Likewise. * testsuite/ld-sparc/tlssunbin32.sd: Likewise. * testsuite/ld-sparc/tlssunbin64.dd: Likewise. * testsuite/ld-sparc/tlssunbin64.rd: Likewise. * testsuite/ld-sparc/tlssunbin64.sd: Likewise.
Diffstat (limited to 'bfd/elfxx-sparc.c')
-rw-r--r--bfd/elfxx-sparc.c31
1 files changed, 13 insertions, 18 deletions
diff --git a/bfd/elfxx-sparc.c b/bfd/elfxx-sparc.c
index f99d052..9f9feda 100644
--- a/bfd/elfxx-sparc.c
+++ b/bfd/elfxx-sparc.c
@@ -1333,7 +1333,7 @@ sparc_elf_tls_transition (struct bfd_link_info *info, bfd *abfd,
&& ! _bfd_sparc_elf_tdata (abfd)->has_tlsgd)
r_type = R_SPARC_REV32;
- if (!bfd_link_executable (info))
+ if (bfd_link_pic (info))
return r_type;
switch (r_type)
@@ -1505,13 +1505,13 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
case R_SPARC_TLS_LE_HIX22:
case R_SPARC_TLS_LE_LOX10:
- if (!bfd_link_executable (info))
+ if (bfd_link_pic (info))
goto r_sparc_plt32;
break;
case R_SPARC_TLS_IE_HI22:
case R_SPARC_TLS_IE_LO10:
- if (!bfd_link_executable (info))
+ if (bfd_link_pic (info))
info->flags |= DF_STATIC_TLS;
/* Fall through */
@@ -1625,18 +1625,13 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
case R_SPARC_TLS_GD_CALL:
case R_SPARC_TLS_LDM_CALL:
- if (!bfd_link_executable (info))
+ if (bfd_link_pic (info))
{
/* These are basically R_SPARC_TLS_WPLT30 relocs against
__tls_get_addr. */
- struct bfd_link_hash_entry *bh = NULL;
- if (! _bfd_generic_link_add_one_symbol (info, abfd,
- "__tls_get_addr", 0,
- bfd_und_section_ptr, 0,
- NULL, FALSE, FALSE,
- &bh))
- return FALSE;
- h = (struct elf_link_hash_entry *) bh;
+ h = (struct elf_link_hash_entry *)
+ bfd_link_hash_lookup (info->hash, "__tls_get_addr", TRUE,
+ FALSE, TRUE);
}
else
break;
@@ -2232,7 +2227,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
/* If R_SPARC_TLS_IE_{HI22,LO10} symbol is now local to the binary,
make it a R_SPARC_TLS_LE_{HI22,LO10} requiring no TLS entry. */
if (h->got.refcount > 0
- && bfd_link_executable (info)
+ && !bfd_link_pic (info)
&& h->dynindx == -1
&& _bfd_sparc_elf_hash_entry(h)->tls_type == GOT_TLS_IE)
h->got.offset = (bfd_vma) -1;
@@ -3576,7 +3571,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
else if (h != NULL)
{
tls_type = _bfd_sparc_elf_hash_entry(h)->tls_type;
- if (bfd_link_executable (info)
+ if (!bfd_link_pic (info)
&& h->dynindx == -1
&& tls_type == GOT_TLS_IE)
switch (SPARC_ELF_R_TYPE (rel->r_info))
@@ -3723,7 +3718,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
case R_SPARC_TLS_LE_HIX22:
case R_SPARC_TLS_LE_LOX10:
- if (!bfd_link_executable (info))
+ if (bfd_link_pic (info))
{
Elf_Internal_Rela outrel;
bfd_boolean skip;
@@ -3755,7 +3750,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
break;
case R_SPARC_TLS_LDM_CALL:
- if (bfd_link_executable (info))
+ if (! bfd_link_pic (info))
{
/* mov %g0, %o0 */
bfd_put_32 (output_bfd, 0x90100000, contents + rel->r_offset);
@@ -3769,7 +3764,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
tls_type = _bfd_sparc_elf_local_got_tls_type (input_bfd) [r_symndx];
else if (h != NULL)
tls_type = _bfd_sparc_elf_hash_entry(h)->tls_type;
- if (bfd_link_executable (info)
+ if (! bfd_link_pic (info)
|| (r_type == R_SPARC_TLS_GD_CALL && tls_type == GOT_TLS_IE))
{
Elf_Internal_Rela *rel2;
@@ -3878,7 +3873,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
case R_SPARC_TLS_IE_LD:
case R_SPARC_TLS_IE_LDX:
- if (bfd_link_executable (info) && (h == NULL || h->dynindx == -1))
+ if (! bfd_link_pic (info) && (h == NULL || h->dynindx == -1))
{
bfd_vma insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
int rs2 = insn & 0x1f;