diff options
author | Alan Modra <amodra@gmail.com> | 2011-03-23 15:25:06 +0000 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2011-03-23 15:25:06 +0000 |
commit | 663a1470e1a7af58a3d0691f480bc5621bd0c54f (patch) | |
tree | eb7a84aef9f6d307fdb4f8472b0e1759b04f6625 /bfd/elf32-ppc.c | |
parent | 6f8a4444ff2b2239ccc23fb175f89d8c5fc4435f (diff) | |
download | gdb-663a1470e1a7af58a3d0691f480bc5621bd0c54f.zip gdb-663a1470e1a7af58a3d0691f480bc5621bd0c54f.tar.gz gdb-663a1470e1a7af58a3d0691f480bc5621bd0c54f.tar.bz2 |
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 fcbfa83..9e097ad 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) |