aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf32-ppc.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2017-07-16 11:50:52 +0930
committerAlan Modra <amodra@gmail.com>2017-07-16 21:31:38 +0930
commit676ee2b5fa6ae41342a9fcd2b7ca18693fa0535b (patch)
treeab531ec9bcdc592b84ba9ccb60845219df2d203e /bfd/elf32-ppc.c
parent046c08c44b786410bc743963578ce90b5c21e468 (diff)
__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.
Diffstat (limited to 'bfd/elf32-ppc.c')
-rw-r--r--bfd/elf32-ppc.c37
1 files changed, 2 insertions, 35 deletions
diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index 27d62ab00a..6d8b5020f5 100644
--- a/bfd/elf32-ppc.c
+++ b/bfd/elf32-ppc.c
@@ -8639,10 +8639,6 @@ ppc_elf_relocate_section (bfd *output_bfd,
else
{
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)
{
@@ -8654,8 +8650,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
value = 0;
else
value -= htab->elf.tls_sec->vma + DTP_OFFSET;
- if ((tls_ty & TLS_TPREL)
- || (tlsopt && !(tls_ty & TLS_DTPREL)))
+ if (tls_ty & TLS_TPREL)
value += DTP_OFFSET - TP_OFFSET;
}
@@ -8663,7 +8658,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
{
bfd_put_32 (input_bfd, value,
htab->elf.sgot->contents + off + 4);
- value = !tlsopt;
+ value = 1;
}
}
bfd_put_32 (input_bfd, value,
@@ -9008,34 +9003,6 @@ ppc_elf_relocate_section (bfd *output_bfd,
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;
case R_PPC_RELAX_PLT: