* 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.
This commit is contained in:
parent
68eb299672
commit
0d4792f716
@ -1,3 +1,14 @@
|
||||
2003-10-23 Alan Modra <amodra@bigpond.net.au>
|
||||
|
||||
* 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.
|
||||
|
||||
2003-10-22 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
* peicode.h (coff_swap_scnhdr_in): Only remove padding when
|
||||
|
||||
117
bfd/elf64-ppc.c
117
bfd/elf64-ppc.c
@ -4791,11 +4791,12 @@ get_sym_h (struct elf_link_hash_entry **hp, Elf_Internal_Sym **symp,
|
||||
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 +4825,14 @@ get_tls_mask (char **tls_maskp, Elf_Internal_Sym **locsymsp,
|
||||
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 +5316,7 @@ ppc64_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
|
||||
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 +6900,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 +7306,9 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
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 +7342,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
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 +7360,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
unresolved_reloc, info,
|
||||
warned);
|
||||
sym_name = h->root.root.string;
|
||||
sym_type = h->type;
|
||||
}
|
||||
|
||||
/* TLS optimizations. Replace instruction sequences and relocs
|
||||
@ -7368,6 +7369,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
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 +7380,42 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
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 +7430,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
|| (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 +7445,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
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 +7491,20 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
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 +7540,20 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
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 +7652,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
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 +7670,10 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
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;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user