diff options
author | Alan Modra <amodra@bigpond.net.au> | 2011-03-23 15:25:00 +0000 |
---|---|---|
committer | Alan Modra <amodra@bigpond.net.au> | 2011-03-23 15:25:00 +0000 |
commit | 7c92bf98aa9f421cc72129a38221f74f0889b3eb (patch) | |
tree | 54af91ab0007795d44a8bda8b4df4453bf926ca0 /bfd/elf32-ppc.c | |
parent | d94fb7cee92b0d1252b447d6832731d19b660dd0 (diff) | |
download | binutils-redhat-7c92bf98aa9f421cc72129a38221f74f0889b3eb.tar.gz |
bfd/
* elf32-ppc.c (ppc_elf_tls_optimize): Catch more cases where
old-style __tls_get_addr calls without marker relocs don't match
their arg setup insn one for one. If such mismatches are found
report the reloc and don't do any tls optimization.
* elf64-ppc.c (ppc64_elf_tls_optimize): Likewise.
ld/testsuite/
* ld-powerpc/tlsmark.s: Delete non-optimizable section.
* ld-powerpc/tlsmark32.s: Likewise.
* ld-powerpc/tlsmark.d: Adjust to suit.
* ld-powerpc/tlsmark32.d: Likewise.
* ld-powerpc/tlsopt1.d, * ld-powerpc/tlsopt1.s: New.
* ld-powerpc/tlsopt2.d, * ld-powerpc/tlsopt2.s: New.
* ld-powerpc/tlsopt3.d, * ld-powerpc/tlsopt3.s: New.
* ld-powerpc/tlsopt4.d, * ld-powerpc/tlsopt4.s: New.
* ld-powerpc/tlsopt1_32.d, * ld-powerpc/tlsopt1_32.s: New.
* ld-powerpc/tlsopt2_32.d, * ld-powerpc/tlsopt2_32.s: New.
* ld-powerpc/tlsopt3_32.d, * ld-powerpc/tlsopt3_32.s: New.
* ld-powerpc/tlsopt4_32.d, * ld-powerpc/tlsopt4_32.s: New.
* ld-powerpc/powerpc.exp: Run new tests.
Diffstat (limited to 'bfd/elf32-ppc.c')
-rw-r--r-- | bfd/elf32-ppc.c | 44 |
1 files changed, 37 insertions, 7 deletions
diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index fcbfa8337b..9e097ad624 100644 --- a/bfd/elf32-ppc.c +++ b/bfd/elf32-ppc.c @@ -4631,10 +4631,15 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, return TRUE; htab = ppc_elf_hash_table (info); + if (htab == NULL) + return FALSE; + /* Make two passes through the relocs. First time check that tls relocs involved in setting up a tls_get_addr call are indeed - followed by such a call. If they are not, exclude them from - the optimizations done on the second pass. */ + followed by such a call. If they are not, don't do any tls + optimization. On the second pass twiddle tls_mask flags to + notify relocate_section that optimization can be done, and + adjust got and plt refcounts. */ for (pass = 0; pass < 2; ++pass) for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) { @@ -4646,6 +4651,7 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, if (sec->has_tls_reloc && !bfd_is_abs_section (sec->output_section)) { Elf_Internal_Rela *relstart, *rel, *relend; + int expecting_tls_get_addr = 0; /* Read the relocations. */ relstart = _bfd_elf_link_read_relocs (ibfd, sec, NULL, NULL, @@ -4662,7 +4668,6 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, char *tls_mask; char tls_set, tls_clear; bfd_boolean is_local; - int expecting_tls_get_addr; bfd_signed_vma *got_count; r_symndx = ELF32_R_SYM (rel->r_info); @@ -4677,13 +4682,34 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, h = (struct elf_link_hash_entry *) h->root.u.i.link; } - expecting_tls_get_addr = 0; is_local = FALSE; if (h == NULL || !h->def_dynamic) is_local = TRUE; r_type = ELF32_R_TYPE (rel->r_info); + /* If this section has old-style __tls_get_addr calls + without marker relocs, then check that each + __tls_get_addr call reloc is preceded by a reloc + that conceivably belongs to the __tls_get_addr arg + setup insn. If we don't find matching arg setup + relocs, don't do any tls optimization. */ + if (pass == 0 + && sec->has_tls_get_addr_call + && h != NULL + && h == htab->tls_get_addr + && !expecting_tls_get_addr + && is_branch_reloc (r_type)) + { + info->callbacks->minfo ("%C __tls_get_addr lost arg, " + "TLS optimization disabled\n", + ibfd, sec, rel->r_offset); + if (elf_section_data (sec)->relocs != relstart) + free (relstart); + return TRUE; + } + + expecting_tls_get_addr = 0; switch (r_type) { case R_PPC_GOT_TLSLD16: @@ -4760,9 +4786,13 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, /* Uh oh, we didn't find the expected call. We could just mark this symbol to exclude it from tls optimization but it's safer to skip - the entire section. */ - sec->has_tls_reloc = 0; - break; + the entire optimization. */ + info->callbacks->minfo (_("%C arg lost __tls_get_addr, " + "TLS optimization disabled\n"), + ibfd, sec, rel->r_offset); + if (elf_section_data (sec)->relocs != relstart) + free (relstart); + return TRUE; } if (expecting_tls_get_addr) |