PowerPC indirect calls to __tls_get_addr
authorAlan Modra <amodra@gmail.com>
Sun, 8 Apr 2018 23:41:44 +0000 (09:11 +0930)
committerAlan Modra <amodra@gmail.com>
Mon, 9 Apr 2018 07:23:05 +0000 (16:53 +0930)
commit37da22e5c85375b30e1211ecff1b261f425375f0
tree7df19745933aff7448284642e17d626b5270358c
parent51066b93507b79e46bcd6c998b760a2fd4b3d0a9
PowerPC indirect calls to __tls_get_addr

It is possible to construct indirect calls to __tls_get_addr in
assembly that confuse TLS optimization.  (PowerPC gcc doesn't support
such calls, ignoring -mlongcall for __tls_get_addr.)  This patch fixes
the problem by requiring a TLSLD or TLSGD marker reloc before any insn
in an indirect call to __tls_get_addr will be optimized.  They also
need additional marker relocs defined in a later patch, so don't
expect the optimization to work just yet.  The point here is to
prevent mis-optimization of indirect calls without any marker relocs.

The presense of a marker reloc is tracked by a new bit in the tls_mask
field of ppc_link_hash_entry and the corresponding lgot_masks unsigned
char array for local symbols.  Since the field is only 8 bits, we've
run out of space.  However, tracking TLS use for variables, and
tracking IFUNC for functions are independent, and bits can be reused.
TLS_TLS is always set for TLS usage, so can be used to select the
meaning of the other bits.  This patch does that even for elf32-ppc.c
which hasn't yet run out of space in the field.

* elf64-ppc.c (TLS_TLS, TLS_GD, TLS_LD, TLS_TPREL, TLS_DTPREL,
TLS_TPRELGD, TLS_EXPLICIT):  Renumber.  Test TLS_TLS throughout
file when other TLS flags are tested in a mask.
(TLS_MARK, NON_GOT): Define.
(PLT_IFUNC): Redefine, and test TLS_TLS throughout file as well.
(update_local_sym_info): Don't create got entry when NON_GOT.
(ppc64_elf_check_relocs): Pass NON_GOT with PLT_IFUNC.
Set TLS_MARK.
(get_tls_mask): Do toc lookup if tls_mask is just TLS_MARK.
(ppc64_elf_relocate_section): Likewise.
(ppc64_elf_tls_optimize): Don't attempt to optimize indirect
__tls_get_addr calls lacking a marker reloc.
* elf32-ppc.c (TLS_TLS, TLS_GD, TLS_LD, TLS_TPREL, TLS_DTPREL,
TLS_TPRELGD): Renumber.  Update comment.
(TLS_MARK, NON_GOT): Define.
(PLT_IFUNC): Redefine, and test TLS_TLS throughout file as well.
(update_local_sym_info): Don't create got entry when NON_GOT.
(ppc_elf_check_relocs): Pass NON_GOT with PLT_IFUNC.
Set TLS_MARK.
(ppc_elf_tls_optimize): Don't attempt to optimize indirect
__tls_get_addr calls lacking a marker reloc.
bfd/ChangeLog
bfd/elf32-ppc.c
bfd/elf64-ppc.c