__tls_get_addr_opt GOT entries

My 2017-01-24 patch (commit f0158f44) wrongly applied an optimization
of GOT entries for the __tls_get_addr_opt stub, to shared libraries.

When the TLS segment layout is known, as it is for the executable and
shared libraries loaded at initial program start, powerpc supports a
__tls_get_addr optimization.  On the first call to __tls_get_addr for
a given __tls_index GOT entry, the DTPMOD word is set to zero and the
DTPREL word to the thread pointer offset to the thread variable.  This
allows the __tls_get_addr_opt stub to return that value immediately
without making a call into glibc for any subsequent __tls_get_addr
calls using that __tls_index GOT entry.

That's all fine, but I thought I'd be clever and when the thread
variable is local, set up the GOT entry as if __tls_get_addr had
already been called.  Which is good only for the executable, since ld
cannot know the TLS layout for shared libraries.

Of course, if this only applies to executables there isn't much point
to the optimization.  Normally, GD and LD code in an executable will
be converted to IE or LE, losing the __tls_get_addr call.  So the only
time it will trigger is with --no-tls-optimize.  Thus, revert all
support.

	* elf64-ppc.c (ppc64_elf_relocate_section): Don't optimize
	__tls_index GOT entries when using __tls_get_addr_opt stub.
	* elf32-ppc.c (ppc_elf_relocate_section): Likewise.
This commit is contained in:
Alan Modra 2017-07-16 11:50:52 +09:30
parent 046c08c44b
commit 676ee2b5fa
3 changed files with 10 additions and 70 deletions

View File

@ -1,3 +1,9 @@
2017-07-16 Alan Modra <amodra@gmail.com>
* elf64-ppc.c (ppc64_elf_relocate_section): Don't optimize
__tls_index GOT entries when using __tls_get_addr_opt stub.
* elf32-ppc.c (ppc_elf_relocate_section): Likewise.
2017-07-12 Alan Modra <amodra@gmail.com> 2017-07-12 Alan Modra <amodra@gmail.com>
* po/es.po: Update from translationproject.org/latest/bfd/. * po/es.po: Update from translationproject.org/latest/bfd/.

View File

@ -8639,10 +8639,6 @@ ppc_elf_relocate_section (bfd *output_bfd,
else else
{ {
bfd_vma value = relocation; bfd_vma value = relocation;
int tlsopt = (htab->plt_type == PLT_NEW
&& !htab->params->no_tls_get_addr_opt
&& htab->tls_get_addr != NULL
&& htab->tls_get_addr->plt.plist != NULL);
if (tls_ty != 0) if (tls_ty != 0)
{ {
@ -8654,8 +8650,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
value = 0; value = 0;
else else
value -= htab->elf.tls_sec->vma + DTP_OFFSET; value -= htab->elf.tls_sec->vma + DTP_OFFSET;
if ((tls_ty & TLS_TPREL) if (tls_ty & TLS_TPREL)
|| (tlsopt && !(tls_ty & TLS_DTPREL)))
value += DTP_OFFSET - TP_OFFSET; value += DTP_OFFSET - TP_OFFSET;
} }
@ -8663,7 +8658,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
{ {
bfd_put_32 (input_bfd, value, bfd_put_32 (input_bfd, value,
htab->elf.sgot->contents + off + 4); htab->elf.sgot->contents + off + 4);
value = !tlsopt; value = 1;
} }
} }
bfd_put_32 (input_bfd, value, bfd_put_32 (input_bfd, value,
@ -9008,34 +9003,6 @@ ppc_elf_relocate_section (bfd *output_bfd,
break; break;
} }
} }
else if (r_type == R_PPC_DTPMOD32
&& htab->plt_type == PLT_NEW
&& !htab->params->no_tls_get_addr_opt
&& htab->tls_get_addr != NULL
&& htab->tls_get_addr->plt.plist != NULL)
{
/* Set up for __tls_get_addr_opt stub when this entry
does not have dynamic relocs. */
relocation = 0;
/* Set up the next word for local dynamic. If it turns
out to be global dynamic, the reloc will overwrite
this value. */
if (rel->r_offset + 8 <= input_section->size)
bfd_put_32 (input_bfd, DTP_OFFSET - TP_OFFSET,
contents + rel->r_offset + 4);
}
else if (r_type == R_PPC_DTPREL32
&& htab->plt_type == PLT_NEW
&& !htab->params->no_tls_get_addr_opt
&& htab->tls_get_addr != NULL
&& htab->tls_get_addr->plt.plist != NULL
&& rel > relocs
&& rel[-1].r_info == ELF32_R_INFO (r_symndx, R_PPC_DTPMOD32)
&& rel[-1].r_offset + 4 == rel->r_offset)
{
/* __tls_get_addr_opt stub value. */
addend += DTP_OFFSET - TP_OFFSET;
}
break; break;
case R_PPC_RELAX_PLT: case R_PPC_RELAX_PLT:

View File

@ -14647,11 +14647,6 @@ ppc64_elf_relocate_section (bfd *output_bfd,
emitting a reloc. */ emitting a reloc. */
else else
{ {
int tlsopt
= (htab->params->tls_get_addr_opt
&& htab->tls_get_addr_fd != NULL
&& htab->tls_get_addr_fd->elf.plt.plist != NULL);
relocation += addend; relocation += addend;
if (tls_type != 0) if (tls_type != 0)
{ {
@ -14663,8 +14658,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
relocation = 0; relocation = 0;
else else
relocation -= htab->elf.tls_sec->vma + DTP_OFFSET; relocation -= htab->elf.tls_sec->vma + DTP_OFFSET;
if ((tls_type & TLS_TPREL) if (tls_type & TLS_TPREL)
|| (tlsopt && !(tls_type & TLS_DTPREL)))
relocation += DTP_OFFSET - TP_OFFSET; relocation += DTP_OFFSET - TP_OFFSET;
} }
@ -14672,7 +14666,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
{ {
bfd_put_64 (output_bfd, relocation, bfd_put_64 (output_bfd, relocation,
got->contents + off + 8); got->contents + off + 8);
relocation = !tlsopt; relocation = 1;
} }
} }
bfd_put_64 (output_bfd, relocation, bfd_put_64 (output_bfd, relocation,
@ -15080,32 +15074,6 @@ ppc64_elf_relocate_section (bfd *output_bfd,
addend = outrel.r_offset; addend = outrel.r_offset;
} }
} }
else if (r_type == R_PPC64_DTPMOD64
&& htab->params->tls_get_addr_opt
&& htab->tls_get_addr_fd != NULL
&& htab->tls_get_addr_fd->elf.plt.plist != NULL)
{
/* Set up for __tls_get_addr_opt stub, when this entry
does not have dynamic relocs. */
relocation = 0;
/* Set up the next word for local dynamic. If it turns
out to be global dynamic, the reloc will overwrite
this value. */
if (rel->r_offset + 16 <= input_section->size)
bfd_put_64 (input_bfd, DTP_OFFSET - TP_OFFSET,
contents + rel->r_offset + 8);
}
else if (r_type == R_PPC64_DTPREL64
&& htab->params->tls_get_addr_opt
&& htab->tls_get_addr_fd != NULL
&& htab->tls_get_addr_fd->elf.plt.plist != NULL
&& rel > relocs
&& rel[-1].r_info == ELF64_R_INFO (r_symndx, R_PPC64_DTPMOD64)
&& rel[-1].r_offset + 8 == rel->r_offset)
{
/* __tls_get_addr_opt stub value. */
addend += DTP_OFFSET - TP_OFFSET;
}
break; break;
case R_PPC64_COPY: case R_PPC64_COPY:
@ -15899,4 +15867,3 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd,
#define elf64_bed elf64_powerpc_fbsd_bed #define elf64_bed elf64_powerpc_fbsd_bed
#include "elf64-target.h" #include "elf64-target.h"