* elf64-ppc.c (ppc64_elf_check_relocs): Don't refcount tlsld_got here..
	(ppc64_elf_gc_sweep_hook): ..or here..
	(ppc64_elf_tls_optimize): ..or here.  Make two passes through the
	relocs, ensuring that tls_get_addr calls follow gd and ld relocs.
	(allocate_dynrelocs): Refcount tlsld_got here.
	(ppc64_elf_size_dynamic_sections): Allocate local got and call
	allocate_dynrelocs before allocating tlsld_got.
	(ppc64_elf_relocate_section): Remove check that a tls_get_addr
	call follows gd and ld relocs.
ld/testsuite/
	* ld-powerpc/tlsso.d: Update for changed got alloc order.
	* ld-powerpc/tlsso.r: Likewise.
This commit is contained in:
Alan Modra
2007-11-06 13:49:19 +00:00
parent dffc6a6425
commit 102890f04c
5 changed files with 481 additions and 427 deletions

View File

@ -1,5 +1,15 @@
2007-11-06 Alan Modra <amodra@bigpond.net.au> 2007-11-06 Alan Modra <amodra@bigpond.net.au>
* elf64-ppc.c (ppc64_elf_check_relocs): Don't refcount tlsld_got here..
(ppc64_elf_gc_sweep_hook): ..or here..
(ppc64_elf_tls_optimize): ..or here. Make two passes through the
relocs, ensuring that tls_get_addr calls follow gd and ld relocs.
(allocate_dynrelocs): Refcount tlsld_got here.
(ppc64_elf_size_dynamic_sections): Allocate local got and call
allocate_dynrelocs before allocating tlsld_got.
(ppc64_elf_relocate_section): Remove check that a tls_get_addr
call follows gd and ld relocs.
* elf32-ppc.c (ppc_elf_check_relocs): Don't refcount tlsld_got here.. * elf32-ppc.c (ppc_elf_check_relocs): Don't refcount tlsld_got here..
(ppc_elf_gc_sweep_hook): ..or here.. (ppc_elf_gc_sweep_hook): ..or here..
(ppc_elf_tls_optimize): ..or here. Make two passes through the (ppc_elf_tls_optimize): ..or here. Make two passes through the

View File

@ -3161,7 +3161,8 @@ struct got_entry
/* Unlike other ELF targets, we use separate GOT entries for the same /* Unlike other ELF targets, we use separate GOT entries for the same
symbol referenced from different input files. This is to support symbol referenced from different input files. This is to support
automatic multiple TOC/GOT sections, where the TOC base can vary automatic multiple TOC/GOT sections, where the TOC base can vary
from one input file to another. from one input file to another. FIXME: After group_sections we
ought to merge entries within the group.
Point to the BFD owning this GOT entry. */ Point to the BFD owning this GOT entry. */
bfd *owner; bfd *owner;
@ -4480,7 +4481,6 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
case R_PPC64_GOT_TLSLD16_LO: case R_PPC64_GOT_TLSLD16_LO:
case R_PPC64_GOT_TLSLD16_HI: case R_PPC64_GOT_TLSLD16_HI:
case R_PPC64_GOT_TLSLD16_HA: case R_PPC64_GOT_TLSLD16_HA:
ppc64_tlsld_got (abfd)->refcount += 1;
tls_type = TLS_TLS | TLS_LD; tls_type = TLS_TLS | TLS_LD;
goto dogottls; goto dogottls;
@ -5306,7 +5306,6 @@ ppc64_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
case R_PPC64_GOT_TLSLD16_LO: case R_PPC64_GOT_TLSLD16_LO:
case R_PPC64_GOT_TLSLD16_HI: case R_PPC64_GOT_TLSLD16_HI:
case R_PPC64_GOT_TLSLD16_HA: case R_PPC64_GOT_TLSLD16_HA:
ppc64_tlsld_got (abfd)->refcount -= 1;
tls_type = TLS_TLS | TLS_LD; tls_type = TLS_TLS | TLS_LD;
goto dogot; goto dogot;
@ -6795,6 +6794,7 @@ ppc64_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
bfd *ibfd; bfd *ibfd;
asection *sec; asection *sec;
struct ppc_link_hash_table *htab; struct ppc_link_hash_table *htab;
int pass;
if (info->relocatable || info->shared) if (info->relocatable || info->shared)
return TRUE; return TRUE;
@ -6806,19 +6806,17 @@ ppc64_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
asection *toc = bfd_get_section_by_name (ibfd, ".toc"); asection *toc = bfd_get_section_by_name (ibfd, ".toc");
unsigned char *toc_ref = NULL; unsigned char *toc_ref = NULL;
/* Look at all the sections for this file, with TOC last. */ /* Look at all the sections for this file. Make two passes over
for (sec = (ibfd->sections == toc && toc && toc->next ? toc->next the relocs. On the first pass, mark toc entries involved
: ibfd->sections); with tls relocs, and check that tls relocs involved in
sec != NULL; setting up a tls_get_addr call are indeed followed by such a
sec = (sec == toc ? NULL call. If they are not, exclude them from the optimizations
: sec->next == NULL ? toc done on the second pass. */
: sec->next == toc && toc->next ? toc->next for (pass = 0; pass < 2; ++pass)
: sec->next)) for (sec = ibfd->sections; sec != NULL; sec = sec->next)
if (sec->has_tls_reloc && !bfd_is_abs_section (sec->output_section)) if (sec->has_tls_reloc && !bfd_is_abs_section (sec->output_section))
{ {
Elf_Internal_Rela *relstart, *rel, *relend; Elf_Internal_Rela *relstart, *rel, *relend;
int expecting_tls_get_addr;
long toc_ref_index = 0;
/* Read the relocations. */ /* Read the relocations. */
relstart = _bfd_elf_link_read_relocs (ibfd, sec, NULL, NULL, relstart = _bfd_elf_link_read_relocs (ibfd, sec, NULL, NULL,
@ -6826,7 +6824,6 @@ ppc64_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
if (relstart == NULL) if (relstart == NULL)
return FALSE; return FALSE;
expecting_tls_get_addr = 0;
relend = relstart + sec->reloc_count; relend = relstart + sec->reloc_count;
for (rel = relstart; rel < relend; rel++) for (rel = relstart; rel < relend; rel++)
{ {
@ -6839,6 +6836,8 @@ ppc64_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
char tls_set, tls_clear, tls_type = 0; char tls_set, tls_clear, tls_type = 0;
bfd_vma value; bfd_vma value;
bfd_boolean ok_tprel, is_local; bfd_boolean ok_tprel, is_local;
long toc_ref_index = 0;
int expecting_tls_get_addr = 0;
r_symndx = ELF64_R_SYM (rel->r_info); r_symndx = ELF64_R_SYM (rel->r_info);
if (!get_sym_h (&h, &sym, &sym_sec, &tls_mask, &locsyms, if (!get_sym_h (&h, &sym, &sym_sec, &tls_mask, &locsyms,
@ -6886,12 +6885,14 @@ ppc64_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
{ {
case R_PPC64_GOT_TLSLD16: case R_PPC64_GOT_TLSLD16:
case R_PPC64_GOT_TLSLD16_LO: case R_PPC64_GOT_TLSLD16_LO:
expecting_tls_get_addr = 1;
/* Fall thru */
case R_PPC64_GOT_TLSLD16_HI: case R_PPC64_GOT_TLSLD16_HI:
case R_PPC64_GOT_TLSLD16_HA: case R_PPC64_GOT_TLSLD16_HA:
/* These relocs should never be against a symbol /* These relocs should never be against a symbol
defined in a shared lib. Leave them alone if defined in a shared lib. Leave them alone if
that turns out to be the case. */ that turns out to be the case. */
ppc64_tlsld_got (ibfd)->refcount -= 1;
if (!is_local) if (!is_local)
continue; continue;
@ -6899,11 +6900,13 @@ ppc64_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
tls_set = 0; tls_set = 0;
tls_clear = TLS_LD; tls_clear = TLS_LD;
tls_type = TLS_TLS | TLS_LD; tls_type = TLS_TLS | TLS_LD;
expecting_tls_get_addr = 1;
break; break;
case R_PPC64_GOT_TLSGD16: case R_PPC64_GOT_TLSGD16:
case R_PPC64_GOT_TLSGD16_LO: case R_PPC64_GOT_TLSGD16_LO:
expecting_tls_get_addr = 1;
/* Fall thru */
case R_PPC64_GOT_TLSGD16_HI: case R_PPC64_GOT_TLSGD16_HI:
case R_PPC64_GOT_TLSGD16_HA: case R_PPC64_GOT_TLSGD16_HA:
if (ok_tprel) if (ok_tprel)
@ -6914,14 +6917,12 @@ ppc64_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
tls_set = TLS_TLS | TLS_TPRELGD; tls_set = TLS_TLS | TLS_TPRELGD;
tls_clear = TLS_GD; tls_clear = TLS_GD;
tls_type = TLS_TLS | TLS_GD; tls_type = TLS_TLS | TLS_GD;
expecting_tls_get_addr = 1;
break; break;
case R_PPC64_GOT_TPREL16_DS: case R_PPC64_GOT_TPREL16_DS:
case R_PPC64_GOT_TPREL16_LO_DS: case R_PPC64_GOT_TPREL16_LO_DS:
case R_PPC64_GOT_TPREL16_HI: case R_PPC64_GOT_TPREL16_HI:
case R_PPC64_GOT_TPREL16_HA: case R_PPC64_GOT_TPREL16_HA:
expecting_tls_get_addr = 0;
if (ok_tprel) if (ok_tprel)
{ {
/* IE -> LE */ /* IE -> LE */
@ -6930,61 +6931,14 @@ ppc64_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
tls_type = TLS_TLS | TLS_TPREL; tls_type = TLS_TLS | TLS_TPREL;
break; break;
} }
else
continue;
case R_PPC64_REL14:
case R_PPC64_REL14_BRTAKEN:
case R_PPC64_REL14_BRNTAKEN:
case R_PPC64_REL24:
if (h != NULL
&& (h == &htab->tls_get_addr->elf
|| h == &htab->tls_get_addr_fd->elf))
{
if (!expecting_tls_get_addr
&& rel != relstart
&& ((ELF64_R_TYPE (rel[-1].r_info)
== R_PPC64_TOC16)
|| (ELF64_R_TYPE (rel[-1].r_info)
== R_PPC64_TOC16_LO)))
{
/* Check for toc tls entries. */
char *toc_tls;
int retval;
retval = get_tls_mask (&toc_tls, NULL, &locsyms,
rel - 1, ibfd);
if (retval == 0)
goto err_free_rel;
if (retval > 1 && toc_tls != NULL)
{
expecting_tls_get_addr = 1;
if (toc_ref != NULL)
toc_ref[toc_ref_index] = 1;
}
}
if (expecting_tls_get_addr)
{
struct plt_entry *ent;
for (ent = h->plt.plist; ent; ent = ent->next)
if (ent->addend == 0)
{
if (ent->plt.refcount > 0)
ent->plt.refcount -= 1;
break;
}
}
}
expecting_tls_get_addr = 0;
continue; continue;
case R_PPC64_TOC16: case R_PPC64_TOC16:
case R_PPC64_TOC16_LO: case R_PPC64_TOC16_LO:
case R_PPC64_TLS: case R_PPC64_TLS:
expecting_tls_get_addr = 0; if (sym_sec == NULL || sym_sec != toc)
if (sym_sec == toc && toc != NULL) continue;
{
/* Mark this toc entry as referenced by a TLS /* Mark this toc entry as referenced by a TLS
code sequence. We can do that now in the code sequence. We can do that now in the
case of R_PPC64_TLS, and after checking for case of R_PPC64_TLS, and after checking for
@ -7003,13 +6957,22 @@ ppc64_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
BFD_ASSERT (value < toc->size && value % 8 == 0); BFD_ASSERT (value < toc->size && value % 8 == 0);
toc_ref_index = value / 8; toc_ref_index = value / 8;
if (r_type == R_PPC64_TLS) if (r_type == R_PPC64_TLS)
{
toc_ref[toc_ref_index] = 1; toc_ref[toc_ref_index] = 1;
continue;
} }
if (pass != 0 && toc_ref[toc_ref_index] == 0)
continue; continue;
tls_set = 0;
tls_clear = 0;
expecting_tls_get_addr = 2;
break;
case R_PPC64_TPREL64: case R_PPC64_TPREL64:
expecting_tls_get_addr = 0; if (pass == 0
if (sec != toc || sec != toc
|| toc_ref == NULL || toc_ref == NULL
|| !toc_ref[rel->r_offset / 8]) || !toc_ref[rel->r_offset / 8])
continue; continue;
@ -7020,12 +6983,11 @@ ppc64_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
tls_clear = TLS_TPREL; tls_clear = TLS_TPREL;
break; break;
} }
else
continue; continue;
case R_PPC64_DTPMOD64: case R_PPC64_DTPMOD64:
expecting_tls_get_addr = 0; if (pass == 0
if (sec != toc || sec != toc
|| toc_ref == NULL || toc_ref == NULL
|| !toc_ref[rel->r_offset / 8]) || !toc_ref[rel->r_offset / 8])
continue; continue;
@ -7054,10 +7016,110 @@ ppc64_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
break; break;
default: default:
expecting_tls_get_addr = 0;
continue; continue;
} }
if (pass == 0)
{
if (!expecting_tls_get_addr)
continue;
if (rel + 1 < relend)
{
Elf_Internal_Shdr *symtab_hdr;
enum elf_ppc64_reloc_type r_type2;
unsigned long r_symndx2;
struct elf_link_hash_entry *h2;
symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
/* The next instruction should be a call to
__tls_get_addr. Peek at the reloc to be sure. */
r_type2 = ELF64_R_TYPE (rel[1].r_info);
r_symndx2 = ELF64_R_SYM (rel[1].r_info);
if (r_symndx2 >= symtab_hdr->sh_info
&& (r_type2 == R_PPC64_REL14
|| r_type2 == R_PPC64_REL14_BRTAKEN
|| r_type2 == R_PPC64_REL14_BRNTAKEN
|| r_type2 == R_PPC64_REL24))
{
struct elf_link_hash_entry **sym_hashes;
sym_hashes = elf_sym_hashes (ibfd);
h2 = sym_hashes[r_symndx2 - symtab_hdr->sh_info];
while (h2->root.type == bfd_link_hash_indirect
|| h2->root.type == bfd_link_hash_warning)
h2 = ((struct elf_link_hash_entry *)
h2->root.u.i.link);
if (h2 != NULL
&& (h2 == &htab->tls_get_addr->elf
|| h2 == &htab->tls_get_addr_fd->elf))
{
if (expecting_tls_get_addr == 2)
{
/* Check for toc tls entries. */
char *toc_tls;
int retval;
retval = get_tls_mask (&toc_tls, NULL,
&locsyms,
rel, ibfd);
if (retval == 0)
goto err_free_rel;
if (retval > 1 && toc_tls != NULL)
toc_ref[toc_ref_index] = 1;
}
continue;
}
}
}
if (expecting_tls_get_addr != 1)
continue;
/* 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;
}
if (expecting_tls_get_addr)
{
struct plt_entry *ent;
for (ent = htab->tls_get_addr->elf.plt.plist;
ent != NULL;
ent = ent->next)
if (ent->addend == 0)
{
if (ent->plt.refcount > 0)
{
ent->plt.refcount -= 1;
expecting_tls_get_addr = 0;
}
break;
}
}
if (expecting_tls_get_addr)
{
struct plt_entry *ent;
for (ent = htab->tls_get_addr_fd->elf.plt.plist;
ent != NULL;
ent = ent->next)
if (ent->addend == 0)
{
if (ent->plt.refcount > 0)
ent->plt.refcount -= 1;
break;
}
}
if (tls_clear == 0)
continue;
if ((tls_set & TLS_EXPLICIT) == 0) if ((tls_set & TLS_EXPLICIT) == 0)
{ {
struct got_entry *ent; struct got_entry *ent;
@ -7693,7 +7755,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
if ((gent->tls_type & TLS_LD) != 0 if ((gent->tls_type & TLS_LD) != 0
&& !h->def_dynamic) && !h->def_dynamic)
{ {
gent->got.offset = ppc64_tlsld_got (gent->owner)->offset; ppc64_tlsld_got (gent->owner)->refcount += 1;
gent->got.offset = (bfd_vma) -1;
continue; continue;
} }
@ -7877,20 +7940,6 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
if (!is_ppc64_elf_target (ibfd->xvec)) if (!is_ppc64_elf_target (ibfd->xvec))
continue; continue;
if (ppc64_tlsld_got (ibfd)->refcount > 0)
{
s = ppc64_elf_tdata (ibfd)->got;
ppc64_tlsld_got (ibfd)->offset = s->size;
s->size += 16;
if (info->shared)
{
srel = ppc64_elf_tdata (ibfd)->relgot;
srel->size += sizeof (Elf64_External_Rela);
}
}
else
ppc64_tlsld_got (ibfd)->offset = (bfd_vma) -1;
for (s = ibfd->sections; s != NULL; s = s->next) for (s = ibfd->sections; s != NULL; s = s->next)
{ {
struct ppc_dyn_relocs *p; struct ppc_dyn_relocs *p;
@ -7934,14 +7983,8 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
{ {
if ((ent->tls_type & *lgot_masks & TLS_LD) != 0) if ((ent->tls_type & *lgot_masks & TLS_LD) != 0)
{ {
if (ppc64_tlsld_got (ibfd)->offset == (bfd_vma) -1) ppc64_tlsld_got (ibfd)->refcount += 1;
{ ent->got.offset = (bfd_vma) -1;
ppc64_tlsld_got (ibfd)->offset = s->size;
s->size += 16;
if (info->shared)
srel->size += sizeof (Elf64_External_Rela);
}
ent->got.offset = ppc64_tlsld_got (ibfd)->offset;
} }
else else
{ {
@ -7969,6 +8012,26 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
sym dynamic relocs. */ sym dynamic relocs. */
elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, info); elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, info);
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
{
if (!is_ppc64_elf_target (ibfd->xvec))
continue;
if (ppc64_tlsld_got (ibfd)->refcount > 0)
{
s = ppc64_elf_tdata (ibfd)->got;
ppc64_tlsld_got (ibfd)->offset = s->size;
s->size += 16;
if (info->shared)
{
asection *srel = ppc64_elf_tdata (ibfd)->relgot;
srel->size += sizeof (Elf64_External_Rela);
}
}
else
ppc64_tlsld_got (ibfd)->offset = (bfd_vma) -1;
}
/* We now have determined the sizes of the various dynamic sections. /* We now have determined the sizes of the various dynamic sections.
Allocate memory for them. */ Allocate memory for them. */
relocs = FALSE; relocs = FALSE;
@ -10118,12 +10181,12 @@ ppc64_elf_relocate_section (bfd *output_bfd,
{ {
tls_gd = TLS_TPRELGD; tls_gd = TLS_TPRELGD;
if (tls_mask != 0 && (tls_mask & TLS_GD) == 0) if (tls_mask != 0 && (tls_mask & TLS_GD) == 0)
goto tls_get_addr_check; goto tls_ldgd_opt;
} }
else if (retval == 3) else if (retval == 3)
{ {
if (tls_mask != 0 && (tls_mask & TLS_LD) == 0) if (tls_mask != 0 && (tls_mask & TLS_LD) == 0)
goto tls_get_addr_check; goto tls_ldgd_opt;
} }
} }
} }
@ -10236,42 +10299,19 @@ ppc64_elf_relocate_section (bfd *output_bfd,
case R_PPC64_GOT_TLSGD16_LO: case R_PPC64_GOT_TLSGD16_LO:
tls_gd = TLS_TPRELGD; tls_gd = TLS_TPRELGD;
if (tls_mask != 0 && (tls_mask & TLS_GD) == 0) if (tls_mask != 0 && (tls_mask & TLS_GD) == 0)
goto tls_get_addr_check; goto tls_ldgd_opt;
break; break;
case R_PPC64_GOT_TLSLD16: case R_PPC64_GOT_TLSLD16:
case R_PPC64_GOT_TLSLD16_LO: case R_PPC64_GOT_TLSLD16_LO:
if (tls_mask != 0 && (tls_mask & TLS_LD) == 0) if (tls_mask != 0 && (tls_mask & TLS_LD) == 0)
{ {
tls_get_addr_check:
if (rel + 1 < relend)
{
enum elf_ppc64_reloc_type r_type2;
unsigned long r_symndx2;
struct elf_link_hash_entry *h2;
bfd_vma insn1, insn2, insn3; bfd_vma insn1, insn2, insn3;
bfd_vma offset; bfd_vma offset;
/* The next instruction should be a call to tls_ldgd_opt:
__tls_get_addr. Peek at the reloc to be sure. */ /* We know that the next reloc is on a tls_get_addr
r_type2 = ELF64_R_TYPE (rel[1].r_info); call, since ppc64_elf_tls_optimize checks this. */
r_symndx2 = ELF64_R_SYM (rel[1].r_info);
if (r_symndx2 < symtab_hdr->sh_info
|| (r_type2 != R_PPC64_REL14
&& r_type2 != R_PPC64_REL14_BRTAKEN
&& r_type2 != R_PPC64_REL14_BRNTAKEN
&& r_type2 != R_PPC64_REL24))
break;
h2 = sym_hashes[r_symndx2 - symtab_hdr->sh_info];
while (h2->root.type == bfd_link_hash_indirect
|| h2->root.type == bfd_link_hash_warning)
h2 = (struct elf_link_hash_entry *) h2->root.u.i.link;
if (h2 == NULL || (h2 != &htab->tls_get_addr->elf
&& h2 != &htab->tls_get_addr_fd->elf))
break;
/* OK, it checks out. Replace the call. */
offset = rel[1].r_offset; offset = rel[1].r_offset;
insn1 = bfd_get_32 (output_bfd, insn1 = bfd_get_32 (output_bfd,
contents + rel->r_offset - d_offset); contents + rel->r_offset - d_offset);
@ -10283,7 +10323,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
insn1 &= (1 << 26) - (1 << 2); insn1 &= (1 << 26) - (1 << 2);
insn1 |= 58 << 26; /* ld */ insn1 |= 58 << 26; /* ld */
insn2 = 0x7c636a14; /* add 3,3,13 */ insn2 = 0x7c636a14; /* add 3,3,13 */
rel[1].r_info = ELF64_R_INFO (r_symndx2, R_PPC64_NONE); rel[1].r_info = ELF64_R_INFO (ELF64_R_SYM (rel[1].r_info),
R_PPC64_NONE);
if ((tls_mask & TLS_EXPLICIT) == 0) if ((tls_mask & TLS_EXPLICIT) == 0)
r_type = (((r_type - (R_PPC64_GOT_TLSGD16 & 3)) & 3) r_type = (((r_type - (R_PPC64_GOT_TLSGD16 & 3)) & 3)
+ R_PPC64_GOT_TPREL16_DS); + R_PPC64_GOT_TPREL16_DS);
@ -10318,7 +10359,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
insn2 = NOP; insn2 = NOP;
rel[1].r_offset += 4; rel[1].r_offset += 4;
} }
bfd_put_32 (output_bfd, insn1, contents + rel->r_offset - d_offset); bfd_put_32 (output_bfd, insn1,
contents + rel->r_offset - d_offset);
bfd_put_32 (output_bfd, insn2, contents + offset); bfd_put_32 (output_bfd, insn2, contents + offset);
bfd_put_32 (output_bfd, insn3, contents + offset + 4); bfd_put_32 (output_bfd, insn3, contents + offset + 4);
if (tls_gd == 0 || toc_symndx != 0) if (tls_gd == 0 || toc_symndx != 0)
@ -10329,7 +10371,6 @@ ppc64_elf_relocate_section (bfd *output_bfd,
continue; continue;
} }
} }
}
break; break;
case R_PPC64_DTPMOD64: case R_PPC64_DTPMOD64:

View File

@ -1,5 +1,8 @@
2007-11-06 Alan Modra <amodra@bigpond.net.au> 2007-11-06 Alan Modra <amodra@bigpond.net.au>
* ld-powerpc/tlsso.d: Update for changed got alloc order.
* ld-powerpc/tlsso.r: Likewise.
* ld-powerpc/tlsso32.d: Update for changed got alloc order. * ld-powerpc/tlsso32.d: Update for changed got alloc order.
2007-11-05 Alan Modra <amodra@bigpond.net.au> 2007-11-05 Alan Modra <amodra@bigpond.net.au>

View File

@ -17,40 +17,40 @@ Disassembly of section \.text:
.* 4e 80 04 20 bctr .* 4e 80 04 20 bctr
.* <_start>: .* <_start>:
.* 38 62 80 30 addi r3,r2,-32720 .* 38 62 80 20 addi r3,r2,-32736
.* 4b ff ff e5 bl .* <\.__tls_get_addr> .* 4b ff ff e5 bl .* <\.__tls_get_addr>
.* e8 41 00 28 ld r2,40\(r1\) .* e8 41 00 28 ld r2,40\(r1\)
.* 38 62 80 08 addi r3,r2,-32760 .* 38 62 80 50 addi r3,r2,-32688
.* 4b ff ff d9 bl .* <\.__tls_get_addr> .* 4b ff ff d9 bl .* <\.__tls_get_addr>
.* e8 41 00 28 ld r2,40\(r1\) .* e8 41 00 28 ld r2,40\(r1\)
.* 38 62 80 48 addi r3,r2,-32696 .* 38 62 80 38 addi r3,r2,-32712
.* 4b ff ff cd bl .* <\.__tls_get_addr> .* 4b ff ff cd bl .* <\.__tls_get_addr>
.* e8 41 00 28 ld r2,40\(r1\) .* e8 41 00 28 ld r2,40\(r1\)
.* 38 62 80 08 addi r3,r2,-32760 .* 38 62 80 50 addi r3,r2,-32688
.* 4b ff ff c1 bl .* <\.__tls_get_addr> .* 4b ff ff c1 bl .* <\.__tls_get_addr>
.* e8 41 00 28 ld r2,40\(r1\) .* e8 41 00 28 ld r2,40\(r1\)
.* 39 23 80 40 addi r9,r3,-32704 .* 39 23 80 40 addi r9,r3,-32704
.* 3d 23 00 00 addis r9,r3,0 .* 3d 23 00 00 addis r9,r3,0
.* 81 49 80 48 lwz r10,-32696\(r9\) .* 81 49 80 48 lwz r10,-32696\(r9\)
.* e9 22 80 40 ld r9,-32704\(r2\) .* e9 22 80 30 ld r9,-32720\(r2\)
.* 7d 49 18 2a ldx r10,r9,r3 .* 7d 49 18 2a ldx r10,r9,r3
.* e9 22 80 58 ld r9,-32680\(r2\) .* e9 22 80 48 ld r9,-32696\(r2\)
.* 7d 49 6a 2e lhzx r10,r9,r13 .* 7d 49 6a 2e lhzx r10,r9,r13
.* 89 4d 00 00 lbz r10,0\(r13\) .* 89 4d 00 00 lbz r10,0\(r13\)
.* 3d 2d 00 00 addis r9,r13,0 .* 3d 2d 00 00 addis r9,r13,0
.* 99 49 00 00 stb r10,0\(r9\) .* 99 49 00 00 stb r10,0\(r9\)
.* 38 62 80 18 addi r3,r2,-32744 .* 38 62 80 08 addi r3,r2,-32760
.* 4b ff ff 8d bl .* <\.__tls_get_addr> .* 4b ff ff 8d bl .* <\.__tls_get_addr>
.* e8 41 00 28 ld r2,40\(r1\) .* e8 41 00 28 ld r2,40\(r1\)
.* 38 62 80 08 addi r3,r2,-32760 .* 38 62 80 50 addi r3,r2,-32688
.* 4b ff ff 81 bl .* <\.__tls_get_addr> .* 4b ff ff 81 bl .* <\.__tls_get_addr>
.* e8 41 00 28 ld r2,40\(r1\) .* e8 41 00 28 ld r2,40\(r1\)
.* f9 43 80 08 std r10,-32760\(r3\) .* f9 43 80 08 std r10,-32760\(r3\)
.* 3d 23 00 00 addis r9,r3,0 .* 3d 23 00 00 addis r9,r3,0
.* 91 49 80 10 stw r10,-32752\(r9\) .* 91 49 80 10 stw r10,-32752\(r9\)
.* e9 22 80 28 ld r9,-32728\(r2\) .* e9 22 80 18 ld r9,-32744\(r2\)
.* 7d 49 19 2a stdx r10,r9,r3 .* 7d 49 19 2a stdx r10,r9,r3
.* e9 22 80 58 ld r9,-32680\(r2\) .* e9 22 80 48 ld r9,-32696\(r2\)
.* 7d 49 6b 2e sthx r10,r9,r13 .* 7d 49 6b 2e sthx r10,r9,r13
.* e9 4d 00 02 lwa r10,0\(r13\) .* e9 4d 00 02 lwa r10,0\(r13\)
.* 3d 2d 00 00 addis r9,r13,0 .* 3d 2d 00 00 addis r9,r13,0

View File

@ -53,9 +53,9 @@ Relocation section '\.rela\.dyn' at offset .* contains 16 entries:
[0-9a-f ]+R_PPC64_TPREL16_HA +0+105f0 \.tdata \+ 30 [0-9a-f ]+R_PPC64_TPREL16_HA +0+105f0 \.tdata \+ 30
[0-9a-f ]+R_PPC64_TPREL16_LO +0+105f0 \.tdata \+ 30 [0-9a-f ]+R_PPC64_TPREL16_LO +0+105f0 \.tdata \+ 30
[0-9a-f ]+R_PPC64_DTPMOD64 +0+ [0-9a-f ]+R_PPC64_DTPMOD64 +0+
[0-9a-f ]+R_PPC64_DTPMOD64 +0+
[0-9a-f ]+R_PPC64_DTPREL64 +0+ [0-9a-f ]+R_PPC64_DTPREL64 +0+
[0-9a-f ]+R_PPC64_DTPREL64 +0+18 [0-9a-f ]+R_PPC64_DTPREL64 +0+18
[0-9a-f ]+R_PPC64_DTPMOD64 +0+
[0-9a-f ]+R_PPC64_DTPMOD64 +0+ gd \+ 0 [0-9a-f ]+R_PPC64_DTPMOD64 +0+ gd \+ 0
[0-9a-f ]+R_PPC64_DTPREL64 +0+ gd \+ 0 [0-9a-f ]+R_PPC64_DTPREL64 +0+ gd \+ 0
[0-9a-f ]+R_PPC64_DTPREL64 +0+50 ld2 \+ 0 [0-9a-f ]+R_PPC64_DTPREL64 +0+50 ld2 \+ 0