PR ld/11217

* elf64-ppc.c (ppc64_elf_tls_optimize): Optimize tls sequences
	with relocations against undefined weak symbols.
	(ppc64_elf_relocate_section): Don't optimize calls to undefined
	weak functions if the symbol is dynamic.
	(ppc64_elf_relocate_section): Edit tprel tls sequences.
	* elf32-ppc.c (ppc_elf_relocate_section): Likewise.
	(_bfd_elf_ppc_at_tprel_transform): New function.
	* bfd-in.h (_bfd_elf_ppc_at_tprel_transform): Declare.
	* bfd-in2.h: Regenerate.
This commit is contained in:
Alan Modra 2010-01-25 06:47:16 +00:00
parent d2c7a1a63b
commit 766bc6567a
5 changed files with 116 additions and 11 deletions

View File

@ -1,3 +1,16 @@
2010-01-25 Alan Modra <amodra@gmail.com>
PR ld/11217
* elf64-ppc.c (ppc64_elf_tls_optimize): Optimize tls sequences
with relocations against undefined weak symbols.
(ppc64_elf_relocate_section): Don't optimize calls to undefined
weak functions if the symbol is dynamic.
(ppc64_elf_relocate_section): Edit tprel tls sequences.
* elf32-ppc.c (ppc_elf_relocate_section): Likewise.
(_bfd_elf_ppc_at_tprel_transform): New function.
* bfd-in.h (_bfd_elf_ppc_at_tprel_transform): Declare.
* bfd-in2.h: Regenerate.
2010-01-23 Richard Sandiford <r.sandiford@uk.ibm.com>
* coff-rs6000.c (xcoff_howto_table): Change size to 0 and bitsize to 1.

View File

@ -1,7 +1,7 @@
/* Main header file for the bfd library -- portable access to object files.
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Contributed by Cygnus Support.
@ -911,6 +911,9 @@ extern bfd_boolean elf32_arm_fix_exidx_coverage
/* PowerPC @tls opcode transform/validate. */
extern unsigned int _bfd_elf_ppc_at_tls_transform
(unsigned int, unsigned int);
/* PowerPC @tprel opcode transform/validate. */
extern unsigned int _bfd_elf_ppc_at_tprel_transform
(unsigned int, unsigned int);
/* TI COFF load page support. */
extern void bfd_ticoff_set_section_load_page

View File

@ -8,7 +8,7 @@
/* Main header file for the bfd library -- portable access to object files.
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Contributed by Cygnus Support.
@ -918,6 +918,9 @@ extern bfd_boolean elf32_arm_fix_exidx_coverage
/* PowerPC @tls opcode transform/validate. */
extern unsigned int _bfd_elf_ppc_at_tls_transform
(unsigned int, unsigned int);
/* PowerPC @tprel opcode transform/validate. */
extern unsigned int _bfd_elf_ppc_at_tprel_transform
(unsigned int, unsigned int);
/* TI COFF load page support. */
extern void bfd_ticoff_set_section_load_page

View File

@ -1,6 +1,6 @@
/* PowerPC-specific support for 32-bit ELF
Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support.
This file is part of BFD, the Binary File Descriptor library.
@ -6669,6 +6669,51 @@ _bfd_elf_ppc_at_tls_transform (unsigned int insn, unsigned int reg)
return insn;
}
/* If INSN is an opcode that may be used with an @tprel operand, return
the transformed insn for an undefined weak symbol, ie. with the
thread pointer REG operand removed. Otherwise return 0. */
unsigned int
_bfd_elf_ppc_at_tprel_transform (unsigned int insn, unsigned int reg)
{
if ((insn & (0x1f << 16)) == reg << 16
&& ((insn & (0x3f << 26)) == 14u << 26 /* addi */
|| (insn & (0x3f << 26)) == 15u << 26 /* addis */
|| (insn & (0x3f << 26)) == 32u << 26 /* lwz */
|| (insn & (0x3f << 26)) == 34u << 26 /* lbz */
|| (insn & (0x3f << 26)) == 36u << 26 /* stw */
|| (insn & (0x3f << 26)) == 38u << 26 /* stb */
|| (insn & (0x3f << 26)) == 40u << 26 /* lhz */
|| (insn & (0x3f << 26)) == 42u << 26 /* lha */
|| (insn & (0x3f << 26)) == 44u << 26 /* sth */
|| (insn & (0x3f << 26)) == 46u << 26 /* lmw */
|| (insn & (0x3f << 26)) == 47u << 26 /* stmw */
|| (insn & (0x3f << 26)) == 48u << 26 /* lfs */
|| (insn & (0x3f << 26)) == 50u << 26 /* lfd */
|| (insn & (0x3f << 26)) == 52u << 26 /* stfs */
|| (insn & (0x3f << 26)) == 54u << 26 /* stfd */
|| ((insn & (0x3f << 26)) == 58u << 26 /* lwa,ld,lmd */
&& (insn & 3) != 1)
|| ((insn & (0x3f << 26)) == 62u << 26 /* std, stmd */
&& ((insn & 3) == 0 || (insn & 3) == 3))))
{
insn &= ~(0x1f << 16);
}
else if ((insn & (0x1f << 21)) == reg << 21
&& ((insn & (0x3e << 26)) == 24u << 26 /* ori, oris */
|| (insn & (0x3e << 26)) == 26u << 26 /* xori,xoris */
|| (insn & (0x3e << 26)) == 28u << 26 /* andi,andis */))
{
insn &= ~(0x1f << 21);
insn |= (insn & (0x1f << 16)) << 5;
if ((insn & (0x3e << 26)) == 26 << 26 /* xori,xoris */)
insn -= 2 >> 26; /* convert to ori,oris */
}
else
insn = 0;
return insn;
}
/* The RELOCATE_SECTION function is called by the ELF backend linker
to handle the relocations for a section.
@ -7471,6 +7516,21 @@ ppc_elf_relocate_section (bfd *output_bfd,
case R_PPC_TPREL16_LO:
case R_PPC_TPREL16_HI:
case R_PPC_TPREL16_HA:
if (h != NULL
&& h->root.type == bfd_link_hash_undefweak
&& h->dynindx == -1)
{
/* Make this relocation against an undefined weak symbol
resolve to zero. This is really just a tweak, since
code using weak externs ought to check that they are
defined before using them. */
bfd_byte *p = contents + rel->r_offset - d_offset;
unsigned int insn = bfd_get_32 (output_bfd, p);
insn = _bfd_elf_ppc_at_tprel_transform (insn, 2);
if (insn != 0)
bfd_put_32 (output_bfd, insn, p);
break;
}
addend -= htab->elf.tls_sec->vma + TP_OFFSET;
/* The TPREL16 relocs shouldn't really be used in shared
libs as they will result in DT_TEXTREL being set, but

View File

@ -7409,10 +7409,13 @@ ppc64_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
if (h != NULL)
{
if (h->root.type != bfd_link_hash_defined
&& h->root.type != bfd_link_hash_defweak)
if (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
value = h->root.u.def.value;
else if (h->root.type == bfd_link_hash_undefweak)
value = 0;
else
continue;
value = h->root.u.def.value;
}
else
/* Symbols referenced by TLS relocs must be of type
@ -7425,11 +7428,17 @@ ppc64_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
|| !h->def_dynamic)
{
is_local = TRUE;
value += sym_sec->output_offset;
value += sym_sec->output_section->vma;
value -= htab->elf.tls_sec->vma;
ok_tprel = (value + TP_OFFSET + ((bfd_vma) 1 << 31)
< (bfd_vma) 1 << 32);
if (h != NULL
&& h->root.type == bfd_link_hash_undefweak)
ok_tprel = TRUE;
else
{
value += sym_sec->output_offset;
value += sym_sec->output_section->vma;
value -= htab->elf.tls_sec->vma;
ok_tprel = (value + TP_OFFSET + ((bfd_vma) 1 << 31)
< (bfd_vma) 1 << 32);
}
}
r_type = ELF64_R_TYPE (rel->r_info);
@ -11498,6 +11507,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
checking whether the function is defined. */
else if (h != NULL
&& h->elf.root.type == bfd_link_hash_undefweak
&& h->elf.dynindx == -1
&& r_type == R_PPC64_REL24
&& relocation == 0
&& addend == 0)
@ -11833,6 +11843,22 @@ ppc64_elf_relocate_section (bfd *output_bfd,
case R_PPC64_TPREL16_HIGHERA:
case R_PPC64_TPREL16_HIGHEST:
case R_PPC64_TPREL16_HIGHESTA:
if (h != NULL
&& h->elf.root.type == bfd_link_hash_undefweak
&& h->elf.dynindx == -1)
{
/* Make this relocation against an undefined weak symbol
resolve to zero. This is really just a tweak, since
code using weak externs ought to check that they are
defined before using them. */
bfd_byte *p = contents + rel->r_offset - d_offset;
insn = bfd_get_32 (output_bfd, p);
insn = _bfd_elf_ppc_at_tprel_transform (insn, 13);
if (insn != 0)
bfd_put_32 (output_bfd, insn, p);
break;
}
addend -= htab->elf.tls_sec->vma + TP_OFFSET;
if (info->shared)
/* The TPREL16 relocs shouldn't really be used in shared