This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
PowerPC64 tls sanity check
- From: Alan Modra <amodra at bigpond dot net dot au>
- To: binutils at sources dot redhat dot com
- Date: Thu, 23 Oct 2003 18:05:42 +0930
- Subject: PowerPC64 tls sanity check
Implements a ld sanity check for PowerPC64 Linux, guarding against
"extern int x;" in one file and "__thread int x;" in another. In the
process of doing this, I uncovered some problems with tls optimization
for the PowerOpen style tls scheme, so the following fixes those too.
bfd/ChangeLog
* elf64-ppc.c (get_tls_mask): Add toc_symndx param, save toc
reloc symbol index to it. Don't allow gd syms in shared libs
to be optimized.
(ppc64_elf_tls_optimize): Adjust get_tls_mask call.
(ppc64_elf_size_stubs): Likewise.
(ppc64_elf_relocate_section): Check that tls relocs are only used
with tls syms, and similarly for non-tls. Correct symbol used
when optimizing toc tls code.
ld/ChangeLog
* ld-powerpc/tlsexetoc.d: Correct.
* ld-powerpc/tlstoc.d: Correct.
Index: bfd/elf64-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-ppc.c,v
retrieving revision 1.131
diff -u -p -r1.131 elf64-ppc.c
--- bfd/elf64-ppc.c 23 Sep 2003 00:40:49 -0000 1.131
+++ bfd/elf64-ppc.c 23 Oct 2003 07:35:05 -0000
@@ -4791,11 +4801,12 @@ get_sym_h (struct elf_link_hash_entry **
type suitable for optimization, and 1 otherwise. */
static int
-get_tls_mask (char **tls_maskp, Elf_Internal_Sym **locsymsp,
+get_tls_mask (char **tls_maskp, unsigned long *toc_symndx,
+ Elf_Internal_Sym **locsymsp,
const Elf_Internal_Rela *rel, bfd *ibfd)
{
unsigned long r_symndx;
- unsigned int next_r;
+ int next_r;
struct elf_link_hash_entry *h;
Elf_Internal_Sym *sym;
asection *sec;
@@ -4824,17 +4835,14 @@ get_tls_mask (char **tls_maskp, Elf_Inte
next_r = ppc64_elf_section_data (sec)->t_symndx[off / 8 + 1];
if (!get_sym_h (&h, &sym, &sec, tls_maskp, locsymsp, r_symndx, ibfd))
return 0;
- if (h == NULL
- || h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak)
- {
- if (next_r == (unsigned) -1)
- return 2;
- if (next_r == (unsigned) -2
- && (h == NULL
- || !(h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC)))
- return 3;
- }
+ if (toc_symndx != NULL)
+ *toc_symndx = r_symndx;
+ if ((h == NULL
+ || ((h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ && !(h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC)))
+ && (next_r == -1 || next_r == -2))
+ return 1 - next_r;
return 1;
}
@@ -5318,7 +5326,7 @@ ppc64_elf_tls_optimize (bfd *obfd ATTRIB
char *toc_tls;
int retval;
- retval = get_tls_mask (&toc_tls, &locsyms,
+ retval = get_tls_mask (&toc_tls, NULL, &locsyms,
rel - 1, ibfd);
if (retval == 0)
goto err_free_rel;
@@ -6902,7 +6910,7 @@ ppc64_elf_size_stubs (bfd *output_bfd,
/* Get tls info. */
char *tls_mask;
- if (!get_tls_mask (&tls_mask, &local_syms,
+ if (!get_tls_mask (&tls_mask, NULL, &local_syms,
irela - 1, input_bfd))
goto error_ret_free_internal;
if (*tls_mask != 0)
@@ -7308,8 +7316,9 @@ ppc64_elf_relocate_section (bfd *output_
struct elf_link_hash_entry *h;
struct elf_link_hash_entry *fdh;
const char *sym_name;
- unsigned long r_symndx;
+ unsigned long r_symndx, toc_symndx;
char tls_mask, tls_gd, tls_type;
+ char sym_type;
bfd_vma relocation;
bfd_boolean unresolved_reloc;
bfd_boolean warned;
@@ -7343,6 +7352,7 @@ ppc64_elf_relocate_section (bfd *output_
sym = local_syms + r_symndx;
sec = local_sections[r_symndx];
sym_name = bfd_elf_local_sym_name (input_bfd, sym);
+ sym_type = ELF64_ST_TYPE (sym->st_info);
relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
if (elf_section_data (sec) != NULL)
{
@@ -7360,6 +7370,7 @@ ppc64_elf_relocate_section (bfd *output_
unresolved_reloc, info,
warned);
sym_name = h->root.root.string;
+ sym_type = h->type;
}
/* TLS optimizations. Replace instruction sequences and relocs
@@ -7368,6 +7379,7 @@ ppc64_elf_relocate_section (bfd *output_
for the final instruction stream. */
tls_mask = 0;
tls_gd = 0;
+ toc_symndx = 0;
if (IS_PPC64_TLS_RELOC (r_type))
{
if (h != NULL)
@@ -7378,6 +7390,42 @@ ppc64_elf_relocate_section (bfd *output_
lgot_masks = (char *) (local_got_ents + symtab_hdr->sh_info);
tls_mask = lgot_masks[r_symndx];
}
+ if (tls_mask == 0 && r_type == R_PPC64_TLS)
+ {
+ /* Check for toc tls entries. */
+ char *toc_tls;
+
+ if (!get_tls_mask (&toc_tls, &toc_symndx, &local_syms,
+ rel, input_bfd))
+ return FALSE;
+
+ if (toc_tls)
+ tls_mask = *toc_tls;
+ }
+ }
+
+ /* Check that tls relocs are used with tls syms, and non-tls
+ relocs are used with non-tls syms. */
+ if (r_symndx != 0
+ && r_type != R_PPC64_NONE
+ && (h == NULL
+ || h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ && IS_PPC64_TLS_RELOC (r_type) != (sym_type == STT_TLS))
+ {
+ if (r_type == R_PPC64_TLS && tls_mask != 0)
+ /* R_PPC64_TLS is OK against a symbol in the TOC. */
+ ;
+ else
+ (*_bfd_error_handler)
+ (sym_type == STT_TLS
+ ? _("%s(%s+0x%lx): %s used with TLS symbol %s")
+ : _("%s(%s+0x%lx): %s used with non-TLS symbol %s"),
+ bfd_archive_filename (input_bfd),
+ input_section->name,
+ (long) rel->r_offset,
+ ppc64_elf_howto_table[r_type]->name,
+ sym_name);
}
/* Ensure reloc mapping code below stays sane. */
@@ -7392,6 +7440,7 @@ ppc64_elf_relocate_section (bfd *output_
|| (R_PPC64_GOT_TLSLD16_HI & 3) != (R_PPC64_GOT_TPREL16_HI & 3)
|| (R_PPC64_GOT_TLSLD16_HA & 3) != (R_PPC64_GOT_TPREL16_HA & 3))
abort ();
+
switch (r_type)
{
default:
@@ -7406,7 +7455,8 @@ ppc64_elf_relocate_section (bfd *output_
char *toc_tls;
int retval;
- retval = get_tls_mask (&toc_tls, &local_syms, rel, input_bfd);
+ retval = get_tls_mask (&toc_tls, &toc_symndx, &local_syms,
+ rel, input_bfd);
if (retval == 0)
return FALSE;
@@ -7451,22 +7501,20 @@ ppc64_elf_relocate_section (bfd *output_
insn |= 0x3c0d0000; /* addis 0,13,0 */
bfd_put_32 (output_bfd, insn, contents + rel->r_offset - 2);
r_type = R_PPC64_TPREL16_HA;
- rel->r_info = ELF64_R_INFO (r_symndx, r_type);
+ if (toc_symndx != 0)
+ {
+ rel->r_info = ELF64_R_INFO (toc_symndx, r_type);
+ /* We changed the symbol. Start over in order to
+ get h, sym, sec etc. right. */
+ rel--;
+ continue;
+ }
+ else
+ rel->r_info = ELF64_R_INFO (r_symndx, r_type);
}
break;
case R_PPC64_TLS:
- if (tls_mask == 0)
- {
- /* Check for toc tls entries. */
- char *toc_tls;
-
- if (!get_tls_mask (&toc_tls, &local_syms, rel, input_bfd))
- return FALSE;
-
- if (toc_tls)
- tls_mask = *toc_tls;
- }
if (tls_mask != 0
&& (tls_mask & TLS_TPREL) == 0)
{
@@ -7502,11 +7550,20 @@ ppc64_elf_relocate_section (bfd *output_
abort ();
insn |= rtra;
bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
- r_type = R_PPC64_TPREL16_LO;
- rel->r_info = ELF64_R_INFO (r_symndx, r_type);
/* Was PPC64_TLS which sits on insn boundary, now
PPC64_TPREL16_LO which is at insn+2. */
rel->r_offset += 2;
+ r_type = R_PPC64_TPREL16_LO;
+ if (toc_symndx != 0)
+ {
+ rel->r_info = ELF64_R_INFO (toc_symndx, r_type);
+ /* We changed the symbol. Start over in order to
+ get h, sym, sec etc. right. */
+ rel--;
+ continue;
+ }
+ else
+ rel->r_info = ELF64_R_INFO (r_symndx, r_type);
}
break;
@@ -7605,6 +7662,8 @@ ppc64_elf_relocate_section (bfd *output_
rel->r_addend = htab->tls_sec->vma + DTP_OFFSET;
rel[1].r_addend = htab->tls_sec->vma + DTP_OFFSET;
}
+ else if (toc_symndx != 0)
+ r_symndx = toc_symndx;
r_type = R_PPC64_TPREL16_HA;
rel->r_info = ELF64_R_INFO (r_symndx, r_type);
rel[1].r_info = ELF64_R_INFO (r_symndx,
@@ -7621,10 +7680,10 @@ ppc64_elf_relocate_section (bfd *output_
bfd_put_32 (output_bfd, insn1, contents + rel->r_offset - 2);
bfd_put_32 (output_bfd, insn2, contents + offset);
bfd_put_32 (output_bfd, insn3, contents + offset + 4);
- if (tls_gd == 0)
+ if (tls_gd == 0 || toc_symndx != 0)
{
- /* We changed the symbol on an LD reloc. Start over
- in order to get h, sym, sec etc. right. */
+ /* We changed the symbol. Start over in order
+ to get h, sym, sec etc. right. */
rel--;
continue;
}
Index: ld/testsuite/ld-powerpc/tlsexetoc.d
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-powerpc/tlsexetoc.d,v
retrieving revision 1.4
diff -u -p -r1.4 tlsexetoc.d
--- ld/testsuite/ld-powerpc/tlsexetoc.d 16 Jun 2003 10:51:07 -0000 1.4
+++ ld/testsuite/ld-powerpc/tlsexetoc.d 23 Oct 2003 07:35:34 -0000
@@ -18,15 +18,15 @@ Disassembly of section \.text:
.* 4e 80 04 20 bctr
.* <_start>:
-.* e8 62 80 08 ld r3,-32760\(r2\)
-.* 60 00 00 00 nop
-.* 7c 63 6a 14 add r3,r3,r13
+.* 38 62 80 08 addi r3,r2,-32760
+.* 4b ff ff e1 bl .*
+.* e8 41 00 28 ld r2,40\(r1\)
.* 38 62 80 18 addi r3,r2,-32744
.* 4b ff ff d5 bl .*
.* e8 41 00 28 ld r2,40\(r1\)
.* 3c 6d 00 00 addis r3,r13,0
.* 60 00 00 00 nop
-.* 38 63 91 90 addi r3,r3,-28272
+.* 38 63 90 38 addi r3,r3,-28616
.* 3c 6d 00 00 addis r3,r13,0
.* 60 00 00 00 nop
.* 38 63 10 00 addi r3,r3,4096
@@ -36,7 +36,7 @@ Disassembly of section \.text:
.* e9 22 80 48 ld r9,-32696\(r2\)
.* 7d 49 18 2a ldx r10,r9,r3
.* 3d 2d 00 00 addis r9,r13,0
-.* a1 49 91 d8 lhz r10,-28200\(r9\)
+.* a1 49 90 58 lhz r10,-28584\(r9\)
.* 89 4d 90 60 lbz r10,-28576\(r13\)
.* 3d 2d 00 00 addis r9,r13,0
.* 99 49 90 68 stb r10,-28568\(r9\)
Index: ld/testsuite/ld-powerpc/tlstoc.d
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-powerpc/tlstoc.d,v
retrieving revision 1.2
diff -u -p -r1.2 tlstoc.d
--- ld/testsuite/ld-powerpc/tlstoc.d 16 Jun 2003 10:51:07 -0000 1.2
+++ ld/testsuite/ld-powerpc/tlstoc.d 23 Oct 2003 07:35:34 -0000
@@ -15,13 +15,13 @@ Disassembly of section \.text:
.* <_start>:
.* 3c 6d 00 00 addis r3,r13,0
.* 60 00 00 00 nop
-.* 38 63 90 58 addi r3,r3,-28584
+.* 38 63 90 40 addi r3,r3,-28608
.* 3c 6d 00 00 addis r3,r13,0
.* 60 00 00 00 nop
.* 38 63 10 00 addi r3,r3,4096
.* 3c 6d 00 00 addis r3,r13,0
.* 60 00 00 00 nop
-.* 38 63 90 58 addi r3,r3,-28584
+.* 38 63 90 48 addi r3,r3,-28600
.* 3c 6d 00 00 addis r3,r13,0
.* 60 00 00 00 nop
.* 38 63 10 00 addi r3,r3,4096
@@ -31,7 +31,7 @@ Disassembly of section \.text:
.* e9 22 80 40 ld r9,-32704\(r2\)
.* 7d 49 18 2a ldx r10,r9,r3
.* 3d 2d 00 00 addis r9,r13,0
-.* a1 49 90 a0 lhz r10,-28512\(r9\)
+.* a1 49 90 68 lhz r10,-28568\(r9\)
.* 89 4d 90 70 lbz r10,-28560\(r13\)
.* 3d 2d 00 00 addis r9,r13,0
.* 99 49 90 78 stb r10,-28552\(r9\)
--
Alan Modra
IBM OzLabs - Linux Technology Centre