include/elf/

* ppc.h (R_PPC_TLSGD, R_PPC_TLSLD): Add new relocs.
	* ppc64.h (R_PPC64_TLSGD, R_PPC64_TLSLD): Add new relocs.
bfd/
	* reloc.c (BFD_RELOC_PPC_TLSGD, BFD_RELOC_PPC_TLSLD): New.
	* section.c (struct bfd_section): Add has_tls_get_addr_call.
	(BFD_FAKE_SECTION): Init new flag.
	* ecoff.c (bfd_debug_section): Likewise.
	* bfd-in2.h: Regenerate.
	* libbfd.h: Regenerate.
	* elf32-ppc.c (ppc_elf_howto_raw): Add R_PPC_TLSGD and R_PPC_TLSLD.
	(ppc_elf_reloc_type_lookup): Handle new relocs.
	(ppc_elf_check_relocs): Set has_tls_get_addr_call on finding such
	without marker relocs.
	(ppc_elf_tls_optimize): Allow out-of-order __tls_get_addr relocs
	if section has no old-style calls.
	(ppc_elf_relocate_section): Set tls_mask for non-tls relocs too.
	Don't try to optimize new-style __tls_get_addr call when handling
	arg setup relocs.  Instead do so for R_PPC_TLSGD and R_PPC_TLSLD
	relocs.
	* elf64-ppc.c (ppc64_elf_howto_raw): Add R_PPC64_TLSGD, R_PPC64_TLSLD.
	(ppc64_elf_reloc_type_lookup): Handle new relocs.
	(ppc64_elf_check_relocs): Set has_tls_get_addr_call on finding such
	without marker relocs.
	(ppc64_elf_tls_optimize): Allow out-of-order __tls_get_addr relocs
	if section has no old-style calls.  Set toc_ref for new relocs as
	appropriate.
	(ppc64_elf_relocate_section): Set tls_mask for non-tls relocs too.
	Don't try to optimize new-style __tls_get_addr call when handling
	arg setup relocs.  Instead do so for R_PPC_TLSGD and R_PPC_TLSLD
	relocs.
gas/
	* config/tc-ppc.c (ppc_elf_suffix): Error if ppc32 tls got relocs
	have non-zero addend.
	(md_assemble): Parse args of __tls_get_addr calls.
	(md_apply_fix): Handle BFD_RELOC_PPC_TLSGD and BFD_RELOC_PPC_TLSLD.
ld/testsuite/
	* ld-powerpc/tlsmark.s, * ld-powerpc/tlsmark.d: New test.
	* ld-powerpc/tlsmark32.s, * ld-powerpc/tlsmark32.d: New test.
	* ld-powerpc/powerpc.exp: Run them.
This commit is contained in:
Alan Modra 2009-03-04 05:50:50 +00:00
parent 51dec22749
commit 727fc41e07
19 changed files with 834 additions and 203 deletions

View File

@ -1,3 +1,33 @@
2009-03-04 Alan Modra <amodra@bigpond.net.au>
* reloc.c (BFD_RELOC_PPC_TLSGD, BFD_RELOC_PPC_TLSLD): New.
* section.c (struct bfd_section): Add has_tls_get_addr_call.
(BFD_FAKE_SECTION): Init new flag.
* ecoff.c (bfd_debug_section): Likewise.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
* elf32-ppc.c (ppc_elf_howto_raw): Add R_PPC_TLSGD and R_PPC_TLSLD.
(ppc_elf_reloc_type_lookup): Handle new relocs.
(ppc_elf_check_relocs): Set has_tls_get_addr_call on finding such
without marker relocs.
(ppc_elf_tls_optimize): Allow out-of-order __tls_get_addr relocs
if section has no old-style calls.
(ppc_elf_relocate_section): Set tls_mask for non-tls relocs too.
Don't try to optimize new-style __tls_get_addr call when handling
arg setup relocs. Instead do so for R_PPC_TLSGD and R_PPC_TLSLD
relocs.
* elf64-ppc.c (ppc64_elf_howto_raw): Add R_PPC64_TLSGD, R_PPC64_TLSLD.
(ppc64_elf_reloc_type_lookup): Handle new relocs.
(ppc64_elf_check_relocs): Set has_tls_get_addr_call on finding such
without marker relocs.
(ppc64_elf_tls_optimize): Allow out-of-order __tls_get_addr relocs
if section has no old-style calls. Set toc_ref for new relocs as
appropriate.
(ppc64_elf_relocate_section): Set tls_mask for non-tls relocs too.
Don't try to optimize new-style __tls_get_addr call when handling
arg setup relocs. Instead do so for R_PPC_TLSGD and R_PPC_TLSLD
relocs.
2009-03-04 Alan Modra <amodra@bigpond.net.au>
PR 6768

View File

@ -1343,6 +1343,9 @@ typedef struct bfd_section
/* Nonzero if this section has TLS related relocations. */
unsigned int has_tls_reloc:1;
/* Nonzero if this section has a call to __tls_get_addr. */
unsigned int has_tls_get_addr_call:1;
/* Nonzero if this section has a gp reloc. */
unsigned int has_gp_reloc:1;
@ -1603,11 +1606,11 @@ extern asection bfd_ind_section;
/* segment_mark, sec_info_type, use_rela_p, has_tls_reloc, */ \
0, 0, 0, 0, \
\
/* has_gp_reloc, need_finalize_relax, reloc_done, */ \
0, 0, 0, \
/* has_tls_get_addr_call, has_gp_reloc, need_finalize_relax, */ \
0, 0, 0, \
\
/* vma, lma, size, rawsize */ \
0, 0, 0, 0, \
/* reloc_done, vma, lma, size, rawsize */ \
0, 0, 0, 0, 0, \
\
/* output_offset, output_section, alignment_power, */ \
0, (struct bfd_section *) &SEC, 0, \
@ -2928,6 +2931,8 @@ relaxation. */
/* PowerPC and PowerPC64 thread-local storage relocations. */
BFD_RELOC_PPC_TLS,
BFD_RELOC_PPC_TLSGD,
BFD_RELOC_PPC_TLSLD,
BFD_RELOC_PPC_DTPMOD,
BFD_RELOC_PPC_TPREL16,
BFD_RELOC_PPC_TPREL16_LO,

View File

@ -1,6 +1,7 @@
/* Generic ECOFF (Extended-COFF) routines.
Copyright 1990, 1991, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
Original version by Per Bothner.
Full support added by Ian Lance Taylor, ian@cygnus.com.
@ -59,10 +60,10 @@ static asection bfd_debug_section =
0, 0, 1,
/* segment_mark, sec_info_type, use_rela_p, has_tls_reloc, */
0, 0, 0, 0,
/* has_gp_reloc, need_finalize_relax, reloc_done, */
0, 0, 0,
/* vma, lma, size, rawsize, */
0, 0, 0, 0,
/* has_tls_get_addr_call, has_gp_reloc, need_finalize_relax, */
0, 0, 0,
/* reloc_done, vma, lma, size, rawsize, */
0, 0, 0, 0, 0,
/* output_offset, output_section, alignment_power, */
0, NULL, 0,
/* relocation, orelocation, reloc_count, filepos, rel_filepos, */

View File

@ -753,7 +753,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
0xffff, /* dst_mask */
FALSE), /* pcrel_offset */
/* Marker reloc for TLS. */
/* Marker relocs for TLS. */
HOWTO (R_PPC_TLS,
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
@ -768,6 +768,34 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
0, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_PPC_TLSGD,
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_TLSGD", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_PPC_TLSLD,
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_TLSLD", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
FALSE), /* pcrel_offset */
/* Computes the load module index of the load module that contains the
definition of its TLS sym. */
HOWTO (R_PPC_DTPMOD32,
@ -1531,6 +1559,8 @@ ppc_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
case BFD_RELOC_CTOR: r = R_PPC_ADDR32; break;
case BFD_RELOC_PPC_TOC16: r = R_PPC_TOC16; break;
case BFD_RELOC_PPC_TLS: r = R_PPC_TLS; break;
case BFD_RELOC_PPC_TLSGD: r = R_PPC_TLSGD; break;
case BFD_RELOC_PPC_TLSLD: r = R_PPC_TLSLD; break;
case BFD_RELOC_PPC_DTPMOD: r = R_PPC_DTPMOD32; break;
case BFD_RELOC_PPC_TPREL16: r = R_PPC_TPREL16; break;
case BFD_RELOC_PPC_TPREL16_LO: r = R_PPC_TPREL16_LO; break;
@ -3288,6 +3318,7 @@ ppc_elf_check_relocs (bfd *abfd,
const Elf_Internal_Rela *rel;
const Elf_Internal_Rela *rel_end;
asection *got2, *sreloc;
struct elf_link_hash_entry *tga;
if (info->relocatable)
return TRUE;
@ -3313,6 +3344,8 @@ ppc_elf_check_relocs (bfd *abfd,
ppc_elf_howto_init ();
htab = ppc_elf_hash_table (info);
tga = elf_link_hash_lookup (&htab->elf, "__tls_get_addr",
FALSE, FALSE, TRUE);
symtab_hdr = &elf_symtab_hdr (abfd);
sym_hashes = elf_sym_hashes (abfd);
got2 = bfd_get_section_by_name (abfd, ".got2");
@ -3324,7 +3357,7 @@ ppc_elf_check_relocs (bfd *abfd,
unsigned long r_symndx;
enum elf_ppc_reloc_type r_type;
struct elf_link_hash_entry *h;
int tls_type = 0;
int tls_type;
r_symndx = ELF32_R_SYM (rel->r_info);
if (r_symndx < symtab_hdr->sh_info)
@ -3351,9 +3384,44 @@ ppc_elf_check_relocs (bfd *abfd,
BFD_ASSERT (h == htab->elf.hgot);
}
tls_type = 0;
r_type = ELF32_R_TYPE (rel->r_info);
if (h != NULL && h == tga)
switch (r_type)
{
default:
break;
case R_PPC_PLTREL24:
case R_PPC_LOCAL24PC:
case R_PPC_REL24:
case R_PPC_REL14:
case R_PPC_REL14_BRTAKEN:
case R_PPC_REL14_BRNTAKEN:
case R_PPC_ADDR24:
case R_PPC_ADDR14:
case R_PPC_ADDR14_BRTAKEN:
case R_PPC_ADDR14_BRNTAKEN:
if (rel != relocs
&& (ELF32_R_TYPE (rel[-1].r_info) == R_PPC_TLSGD
|| ELF32_R_TYPE (rel[-1].r_info) == R_PPC_TLSLD))
/* We have a new-style __tls_get_addr call with a marker
reloc. */
;
else
/* Mark this section as having an old-style call. */
sec->has_tls_get_addr_call = 1;
break;
}
switch (r_type)
{
case R_PPC_TLSGD:
case R_PPC_TLSLD:
/* These special tls relocs tie a call to __tls_get_addr with
its parameter symbol. */
break;
case R_PPC_GOT_TLSLD16:
case R_PPC_GOT_TLSLD16_LO:
case R_PPC_GOT_TLSLD16_HI:
@ -3607,7 +3675,7 @@ ppc_elf_check_relocs (bfd *abfd,
/* This refers only to functions defined in the shared library. */
case R_PPC_LOCAL24PC:
if (h && h == htab->elf.hgot && htab->plt_type == PLT_UNSET)
if (h != NULL && h == htab->elf.hgot && htab->plt_type == PLT_UNSET)
{
htab->plt_type = PLT_OLD;
htab->old_bfd = abfd;
@ -4484,7 +4552,8 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED,
if (pass == 0)
{
if (!expecting_tls_get_addr)
if (!expecting_tls_get_addr
|| !sec->has_tls_get_addr_call)
continue;
if (rel + 1 < relend
@ -6234,16 +6303,13 @@ ppc_elf_relocate_section (bfd *output_bfd,
for the final instruction stream. */
tls_mask = 0;
tls_gd = 0;
if (IS_PPC_TLS_RELOC (r_type))
if (h != NULL)
tls_mask = ((struct ppc_elf_link_hash_entry *) h)->tls_mask;
else if (local_got_offsets != NULL)
{
if (h != NULL)
tls_mask = ((struct ppc_elf_link_hash_entry *) h)->tls_mask;
else if (local_got_offsets != NULL)
{
char *lgot_masks;
lgot_masks = (char *) (local_got_offsets + symtab_hdr->sh_info);
tls_mask = lgot_masks[r_symndx];
}
char *lgot_masks;
lgot_masks = (char *) (local_got_offsets + symtab_hdr->sh_info);
tls_mask = lgot_masks[r_symndx];
}
/* Ensure reloc mapping code below stays sane. */
@ -6361,7 +6427,17 @@ ppc_elf_relocate_section (bfd *output_bfd,
bfd_vma offset;
tls_ldgd_opt:
offset = rel[1].r_offset;
offset = (bfd_vma) -1;
/* If not using the newer R_PPC_TLSGD/LD to mark
__tls_get_addr calls, we must trust that the call
stays with its arg setup insns, ie. that the next
reloc is the __tls_get_addr call associated with
the current reloc. Edit both insns. */
if (input_section->has_tls_get_addr_call
&& rel + 1 < relend
&& branch_reloc_hash_match (input_bfd, rel + 1,
htab->tls_get_addr))
offset = rel[1].r_offset;
if ((tls_mask & tls_gd) != 0)
{
/* IE */
@ -6369,9 +6445,14 @@ ppc_elf_relocate_section (bfd *output_bfd,
contents + rel->r_offset - d_offset);
insn1 &= (1 << 26) - 1;
insn1 |= 32 << 26; /* lwz */
insn2 = 0x7c631214; /* add 3,3,2 */
rel[1].r_info
= ELF32_R_INFO (ELF32_R_SYM (rel[1].r_info), R_PPC_NONE);
if (offset != (bfd_vma) -1)
{
rel[1].r_info
= ELF32_R_INFO (ELF32_R_SYM (rel[1].r_info),
R_PPC_NONE);
insn2 = 0x7c631214; /* add 3,3,2 */
bfd_put_32 (output_bfd, insn2, contents + offset);
}
r_type = (((r_type - (R_PPC_GOT_TLSGD16 & 3)) & 3)
+ R_PPC_GOT_TPREL16);
rel->r_info = ELF32_R_INFO (r_symndx, r_type);
@ -6380,7 +6461,6 @@ ppc_elf_relocate_section (bfd *output_bfd,
{
/* LE */
insn1 = 0x3c620000; /* addis 3,2,0 */
insn2 = 0x38630000; /* addi 3,3,0 */
if (tls_gd == 0)
{
/* Was an LD reloc. */
@ -6399,14 +6479,17 @@ ppc_elf_relocate_section (bfd *output_bfd,
}
r_type = R_PPC_TPREL16_HA;
rel->r_info = ELF32_R_INFO (r_symndx, r_type);
rel[1].r_info = ELF32_R_INFO (r_symndx,
R_PPC_TPREL16_LO);
rel[1].r_offset += d_offset;
rel[1].r_addend = rel->r_addend;
if (offset != (bfd_vma) -1)
{
rel[1].r_info = ELF32_R_INFO (r_symndx, R_PPC_TPREL16_LO);
rel[1].r_offset = offset + d_offset;
rel[1].r_addend = rel->r_addend;
insn2 = 0x38630000; /* addi 3,3,0 */
bfd_put_32 (output_bfd, insn2, contents + offset);
}
}
bfd_put_32 (output_bfd, insn1,
contents + rel->r_offset - d_offset);
bfd_put_32 (output_bfd, insn2, contents + offset);
if (tls_gd == 0)
{
/* We changed the symbol on an LD reloc. Start over
@ -6416,6 +6499,66 @@ ppc_elf_relocate_section (bfd *output_bfd,
}
}
break;
case R_PPC_TLSGD:
if (tls_mask != 0 && (tls_mask & TLS_GD) == 0)
{
unsigned int insn2;
bfd_vma offset = rel->r_offset;
if ((tls_mask & TLS_TPRELGD) != 0)
{
/* IE */
r_type = R_PPC_NONE;
insn2 = 0x7c631214; /* add 3,3,2 */
}
else
{
/* LE */
r_type = R_PPC_TPREL16_LO;
rel->r_offset += d_offset;
insn2 = 0x38630000; /* addi 3,3,0 */
}
rel->r_info = ELF32_R_INFO (r_symndx, r_type);
bfd_put_32 (output_bfd, insn2, contents + offset);
/* Zap the reloc on the _tls_get_addr call too. */
BFD_ASSERT (offset == rel[1].r_offset);
rel[1].r_info = ELF32_R_INFO (ELF32_R_SYM (rel[1].r_info),
R_PPC_NONE);
}
break;
case R_PPC_TLSLD:
if (tls_mask != 0 && (tls_mask & TLS_LD) == 0)
{
unsigned int insn2;
for (r_symndx = 0;
r_symndx < symtab_hdr->sh_info;
r_symndx++)
if (local_sections[r_symndx] == sec)
break;
if (r_symndx >= symtab_hdr->sh_info)
r_symndx = 0;
rel->r_addend = htab->elf.tls_sec->vma + DTP_OFFSET;
if (r_symndx != 0)
rel->r_addend -= (local_syms[r_symndx].st_value
+ sec->output_offset
+ sec->output_section->vma);
rel->r_info = ELF32_R_INFO (r_symndx, R_PPC_TPREL16_LO);
rel->r_offset += d_offset;
insn2 = 0x38630000; /* addi 3,3,0 */
bfd_put_32 (output_bfd, insn2,
contents + rel->r_offset - d_offset);
/* Zap the reloc on the _tls_get_addr call too. */
BFD_ASSERT (rel->r_offset - d_offset == rel[1].r_offset);
rel[1].r_info = ELF32_R_INFO (ELF32_R_SYM (rel[1].r_info),
R_PPC_NONE);
rel--;
continue;
}
break;
}
/* Handle other relocations that tweak non-addend part of insn. */
@ -6468,6 +6611,8 @@ ppc_elf_relocate_section (bfd *output_bfd,
case R_PPC_NONE:
case R_PPC_TLS:
case R_PPC_TLSGD:
case R_PPC_TLSLD:
case R_PPC_EMB_MRKREF:
case R_PPC_GNU_VTINHERIT:
case R_PPC_GNU_VTENTRY:
@ -6509,6 +6654,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
case R_PPC_GOT16_LO:
case R_PPC_GOT16_HI:
case R_PPC_GOT16_HA:
tls_mask = 0;
dogot:
{
/* Relocation is to the entry for this symbol in the global

View File

@ -1235,7 +1235,7 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
0xfffc, /* dst_mask */
FALSE), /* pcrel_offset */
/* Marker reloc for TLS. */
/* Marker relocs for TLS. */
HOWTO (R_PPC64_TLS,
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
@ -1250,6 +1250,34 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
0, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_PPC64_TLSGD,
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC64_TLSGD", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_PPC64_TLSLD,
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC64_TLSLD", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
FALSE), /* pcrel_offset */
/* Computes the load module index of the load module that contains the
definition of its TLS sym. */
HOWTO (R_PPC64_DTPMOD64,
@ -2031,6 +2059,10 @@ ppc64_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
break;
case BFD_RELOC_PPC_TLS: r = R_PPC64_TLS;
break;
case BFD_RELOC_PPC_TLSGD: r = R_PPC64_TLSGD;
break;
case BFD_RELOC_PPC_TLSLD: r = R_PPC64_TLSLD;
break;
case BFD_RELOC_PPC_DTPMOD: r = R_PPC64_DTPMOD64;
break;
case BFD_RELOC_PPC_TPREL16: r = R_PPC64_TPREL16;
@ -4644,7 +4676,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
unsigned long r_symndx;
struct elf_link_hash_entry *h;
enum elf_ppc64_reloc_type r_type;
int tls_type = 0;
int tls_type;
struct _ppc64_elf_section_data *ppc64_sec;
r_symndx = ELF64_R_SYM (rel->r_info);
@ -4658,9 +4690,42 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
h = (struct elf_link_hash_entry *) h->root.u.i.link;
}
tls_type = 0;
r_type = ELF64_R_TYPE (rel->r_info);
if (h != NULL && (h == tga || h == dottga))
switch (r_type)
{
default:
break;
case R_PPC64_REL24:
case R_PPC64_REL14:
case R_PPC64_REL14_BRTAKEN:
case R_PPC64_REL14_BRNTAKEN:
case R_PPC64_ADDR24:
case R_PPC64_ADDR14:
case R_PPC64_ADDR14_BRTAKEN:
case R_PPC64_ADDR14_BRNTAKEN:
if (rel != relocs
&& (ELF64_R_TYPE (rel[-1].r_info) == R_PPC64_TLSGD
|| ELF64_R_TYPE (rel[-1].r_info) == R_PPC64_TLSLD))
/* We have a new-style __tls_get_addr call with a marker
reloc. */
;
else
/* Mark this section as having an old-style call. */
sec->has_tls_get_addr_call = 1;
break;
}
switch (r_type)
{
case R_PPC64_TLSGD:
case R_PPC64_TLSLD:
/* These special tls relocs tie a call to __tls_get_addr with
its parameter symbol. */
break;
case R_PPC64_GOT_TLSLD16:
case R_PPC64_GOT_TLSLD16_LO:
case R_PPC64_GOT_TLSLD16_HI:
@ -7072,6 +7137,8 @@ ppc64_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
case R_PPC64_TOC16:
case R_PPC64_TOC16_LO:
case R_PPC64_TLS:
case R_PPC64_TLSGD:
case R_PPC64_TLSLD:
if (sym_sec == NULL || sym_sec != toc)
continue;
@ -7092,7 +7159,9 @@ ppc64_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
value += rel->r_addend;
BFD_ASSERT (value < toc->size && value % 8 == 0);
toc_ref_index = value / 8;
if (r_type == R_PPC64_TLS)
if (r_type == R_PPC64_TLS
|| r_type == R_PPC64_TLSGD
|| r_type == R_PPC64_TLSLD)
{
toc_ref[toc_ref_index] = 1;
continue;
@ -7157,7 +7226,8 @@ ppc64_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
if (pass == 0)
{
if (!expecting_tls_get_addr)
if (!expecting_tls_get_addr
|| !sec->has_tls_get_addr_call)
continue;
if (rel + 1 < relend
@ -7276,18 +7346,18 @@ ppc64_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
free (relstart);
}
if (toc_ref != NULL)
free (toc_ref);
if (toc_ref != NULL)
free (toc_ref);
if (locsyms != NULL
&& (elf_symtab_hdr (ibfd).contents != (unsigned char *) locsyms))
{
if (!info->keep_memory)
free (locsyms);
else
elf_symtab_hdr (ibfd).contents = (unsigned char *) locsyms;
}
}
if (locsyms != NULL
&& (elf_symtab_hdr (ibfd).contents != (unsigned char *) locsyms))
{
if (!info->keep_memory)
free (locsyms);
else
elf_symtab_hdr (ibfd).contents = (unsigned char *) locsyms;
}
}
return TRUE;
}
@ -10288,28 +10358,28 @@ ppc64_elf_relocate_section (bfd *output_bfd,
tls_mask = 0;
tls_gd = 0;
toc_symndx = 0;
if (IS_PPC64_TLS_RELOC (r_type))
if (h != NULL)
tls_mask = h->tls_mask;
else if (local_got_ents != NULL)
{
if (h != NULL)
tls_mask = h->tls_mask;
else if (local_got_ents != NULL)
{
char *lgot_masks;
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;
char *lgot_masks;
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
|| r_type == R_PPC64_TLSGD
|| r_type == R_PPC64_TLSLD))
{
/* Check for toc tls entries. */
char *toc_tls;
if (!get_tls_mask (&toc_tls, &toc_symndx, &toc_addend,
&local_syms, rel, input_bfd))
return FALSE;
if (!get_tls_mask (&toc_tls, &toc_symndx, &toc_addend,
&local_syms, rel, input_bfd))
return FALSE;
if (toc_tls)
tls_mask = *toc_tls;
}
if (toc_tls)
tls_mask = *toc_tls;
}
/* Check that tls relocs are used with tls syms, and non-tls
@ -10324,7 +10394,10 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|| (sym_type == STT_SECTION
&& (sec->flags & SEC_THREAD_LOCAL) != 0))))
{
if (r_type == R_PPC64_TLS && tls_mask != 0)
if (tls_mask != 0
&& (r_type == R_PPC64_TLS
|| r_type == R_PPC64_TLSGD
|| r_type == R_PPC64_TLSLD))
/* R_PPC64_TLS is OK against a symbol in the TOC. */
;
else
@ -10520,9 +10593,18 @@ ppc64_elf_relocate_section (bfd *output_bfd,
bfd_vma offset;
tls_ldgd_opt:
/* We know that the next reloc is on a tls_get_addr
call, since ppc64_elf_tls_optimize checks this. */
offset = rel[1].r_offset;
offset = (bfd_vma) -1;
/* If not using the newer R_PPC64_TLSGD/LD to mark
__tls_get_addr calls, we must trust that the call
stays with its arg setup insns, ie. that the next
reloc is the __tls_get_addr call associated with
the current reloc. Edit both insns. */
if (input_section->has_tls_get_addr_call
&& rel + 1 < relend
&& branch_reloc_hash_match (input_bfd, rel + 1,
htab->tls_get_addr,
htab->tls_get_addr_fd))
offset = rel[1].r_offset;
if ((tls_mask & tls_gd) != 0)
{
/* IE */
@ -10531,8 +10613,9 @@ ppc64_elf_relocate_section (bfd *output_bfd,
insn1 &= (1 << 26) - (1 << 2);
insn1 |= 58 << 26; /* ld */
insn2 = 0x7c636a14; /* add 3,3,13 */
rel[1].r_info = ELF64_R_INFO (ELF64_R_SYM (rel[1].r_info),
R_PPC64_NONE);
if (offset != (bfd_vma) -1)
rel[1].r_info = ELF64_R_INFO (ELF64_R_SYM (rel[1].r_info),
R_PPC64_NONE);
if ((tls_mask & TLS_EXPLICIT) == 0)
r_type = (((r_type - (R_PPC64_GOT_TLSGD16 & 3)) & 3)
+ R_PPC64_GOT_TPREL16_DS);
@ -10570,23 +10653,29 @@ ppc64_elf_relocate_section (bfd *output_bfd,
}
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,
R_PPC64_TPREL16_LO);
rel[1].r_offset += d_offset;
rel[1].r_addend = rel->r_addend;
if (offset != (bfd_vma) -1)
{
rel[1].r_info = ELF64_R_INFO (r_symndx,
R_PPC64_TPREL16_LO);
rel[1].r_offset = offset + d_offset;
rel[1].r_addend = rel->r_addend;
}
}
bfd_put_32 (output_bfd, insn1,
contents + rel->r_offset - d_offset);
insn3 = bfd_get_32 (output_bfd,
contents + offset + 4);
if (insn3 == NOP
|| insn3 == CROR_151515 || insn3 == CROR_313131)
if (offset != (bfd_vma) -1)
{
rel[1].r_offset += 4;
bfd_put_32 (output_bfd, insn2, contents + offset + 4);
insn2 = NOP;
insn3 = bfd_get_32 (output_bfd,
contents + offset + 4);
if (insn3 == NOP
|| insn3 == CROR_151515 || insn3 == CROR_313131)
{
rel[1].r_offset += 4;
bfd_put_32 (output_bfd, insn2, contents + offset + 4);
insn2 = NOP;
}
bfd_put_32 (output_bfd, insn2, contents + offset);
}
bfd_put_32 (output_bfd, insn2, contents + offset);
if ((tls_mask & tls_gd) == 0
&& (tls_gd == 0 || toc_symndx != 0))
{
@ -10598,6 +10687,97 @@ ppc64_elf_relocate_section (bfd *output_bfd,
}
break;
case R_PPC64_TLSGD:
if (tls_mask != 0 && (tls_mask & TLS_GD) == 0)
{
unsigned int insn2, insn3;
bfd_vma offset = rel->r_offset;
if ((tls_mask & TLS_TPRELGD) != 0)
{
/* IE */
r_type = R_PPC64_NONE;
insn2 = 0x7c636a14; /* add 3,3,13 */
}
else
{
/* LE */
if (toc_symndx != 0)
{
r_symndx = toc_symndx;
rel->r_addend = toc_addend;
}
r_type = R_PPC64_TPREL16_LO;
rel->r_offset = offset + d_offset;
insn2 = 0x38630000; /* addi 3,3,0 */
}
rel->r_info = ELF64_R_INFO (r_symndx, r_type);
/* Zap the reloc on the _tls_get_addr call too. */
BFD_ASSERT (offset == rel[1].r_offset);
rel[1].r_info = ELF64_R_INFO (ELF64_R_SYM (rel[1].r_info),
R_PPC64_NONE);
insn3 = bfd_get_32 (output_bfd,
contents + offset + 4);
if (insn3 == NOP
|| insn3 == CROR_151515 || insn3 == CROR_313131)
{
rel->r_offset += 4;
bfd_put_32 (output_bfd, insn2, contents + offset + 4);
insn2 = NOP;
}
bfd_put_32 (output_bfd, insn2, contents + offset);
if ((tls_mask & TLS_TPRELGD) == 0 && toc_symndx != 0)
{
rel--;
continue;
}
}
break;
case R_PPC64_TLSLD:
if (tls_mask != 0 && (tls_mask & TLS_LD) == 0)
{
unsigned int insn2, insn3;
bfd_vma offset = rel->r_offset;
if (toc_symndx)
sec = local_sections[toc_symndx];
for (r_symndx = 0;
r_symndx < symtab_hdr->sh_info;
r_symndx++)
if (local_sections[r_symndx] == sec)
break;
if (r_symndx >= symtab_hdr->sh_info)
r_symndx = 0;
rel->r_addend = htab->elf.tls_sec->vma + DTP_OFFSET;
if (r_symndx != 0)
rel->r_addend -= (local_syms[r_symndx].st_value
+ sec->output_offset
+ sec->output_section->vma);
r_type = R_PPC64_TPREL16_LO;
rel->r_info = ELF64_R_INFO (r_symndx, r_type);
rel->r_offset = offset + d_offset;
/* Zap the reloc on the _tls_get_addr call too. */
BFD_ASSERT (offset == rel[1].r_offset);
rel[1].r_info = ELF64_R_INFO (ELF64_R_SYM (rel[1].r_info),
R_PPC64_NONE);
insn2 = 0x38630000; /* addi 3,3,0 */
insn3 = bfd_get_32 (output_bfd,
contents + offset + 4);
if (insn3 == NOP
|| insn3 == CROR_151515 || insn3 == CROR_313131)
{
rel->r_offset += 4;
bfd_put_32 (output_bfd, insn2, contents + offset + 4);
insn2 = NOP;
}
bfd_put_32 (output_bfd, insn2, contents + offset);
rel--;
continue;
}
break;
case R_PPC64_DTPMOD64:
if (rel + 1 < relend
&& rel[1].r_info == ELF64_R_INFO (r_symndx, R_PPC64_DTPREL64)
@ -10851,6 +11031,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
case R_PPC64_NONE:
case R_PPC64_TLS:
case R_PPC64_TLSGD:
case R_PPC64_TLSLD:
case R_PPC64_GNU_VTINHERIT:
case R_PPC64_GNU_VTENTRY:
continue;

View File

@ -1201,6 +1201,8 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
"BFD_RELOC_PPC64_PLTGOT16_DS",
"BFD_RELOC_PPC64_PLTGOT16_LO_DS",
"BFD_RELOC_PPC_TLS",
"BFD_RELOC_PPC_TLSGD",
"BFD_RELOC_PPC_TLSLD",
"BFD_RELOC_PPC_DTPMOD",
"BFD_RELOC_PPC_TPREL16",
"BFD_RELOC_PPC_TPREL16_LO",

View File

@ -2710,6 +2710,10 @@ ENUMDOC
ENUM
BFD_RELOC_PPC_TLS
ENUMX
BFD_RELOC_PPC_TLSGD
ENUMX
BFD_RELOC_PPC_TLSLD
ENUMX
BFD_RELOC_PPC_DTPMOD
ENUMX

View File

@ -1,6 +1,6 @@
/* Object file "section" support for the BFD library.
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
Written by Cygnus Support.
@ -382,6 +382,9 @@ CODE_FRAGMENT
. {* Nonzero if this section has TLS related relocations. *}
. unsigned int has_tls_reloc:1;
.
. {* Nonzero if this section has a call to __tls_get_addr. *}
. unsigned int has_tls_get_addr_call:1;
.
. {* Nonzero if this section has a gp reloc. *}
. unsigned int has_gp_reloc:1;
.
@ -642,11 +645,11 @@ CODE_FRAGMENT
. {* segment_mark, sec_info_type, use_rela_p, has_tls_reloc, *} \
. 0, 0, 0, 0, \
. \
. {* has_gp_reloc, need_finalize_relax, reloc_done, *} \
. 0, 0, 0, \
. {* has_tls_get_addr_call, has_gp_reloc, need_finalize_relax, *} \
. 0, 0, 0, \
. \
. {* vma, lma, size, rawsize *} \
. 0, 0, 0, 0, \
. {* reloc_done, vma, lma, size, rawsize *} \
. 0, 0, 0, 0, 0, \
. \
. {* output_offset, output_section, alignment_power, *} \
. 0, (struct bfd_section *) &SEC, 0, \

View File

@ -1,3 +1,10 @@
2009-03-04 Alan Modra <amodra@bigpond.net.au>
* config/tc-ppc.c (ppc_elf_suffix): Error if ppc32 tls got relocs
have non-zero addend.
(md_assemble): Parse args of __tls_get_addr calls.
(md_apply_fix): Handle BFD_RELOC_PPC_TLSGD and BFD_RELOC_PPC_TLSLD.
2009-03-03 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
binutils/3807

View File

@ -1974,13 +1974,38 @@ ppc_elf_suffix (char **str_p, expressionS *exp_p)
{
int reloc = ptr->reloc;
if (!ppc_obj64)
if (exp_p->X_add_number != 0
&& (reloc == (int) BFD_RELOC_16_GOTOFF
|| reloc == (int) BFD_RELOC_LO16_GOTOFF
|| reloc == (int) BFD_RELOC_HI16_GOTOFF
|| reloc == (int) BFD_RELOC_HI16_S_GOTOFF))
as_warn (_("identifier+constant@got means identifier@got+constant"));
if (!ppc_obj64 && exp_p->X_add_number != 0)
{
switch (reloc)
{
case BFD_RELOC_16_GOTOFF:
case BFD_RELOC_LO16_GOTOFF:
case BFD_RELOC_HI16_GOTOFF:
case BFD_RELOC_HI16_S_GOTOFF:
as_warn (_("identifier+constant@got means "
"identifier@got+constant"));
break;
case BFD_RELOC_PPC_GOT_TLSGD16:
case BFD_RELOC_PPC_GOT_TLSGD16_LO:
case BFD_RELOC_PPC_GOT_TLSGD16_HI:
case BFD_RELOC_PPC_GOT_TLSGD16_HA:
case BFD_RELOC_PPC_GOT_TLSLD16:
case BFD_RELOC_PPC_GOT_TLSLD16_LO:
case BFD_RELOC_PPC_GOT_TLSLD16_HI:
case BFD_RELOC_PPC_GOT_TLSLD16_HA:
case BFD_RELOC_PPC_GOT_DTPREL16:
case BFD_RELOC_PPC_GOT_DTPREL16_LO:
case BFD_RELOC_PPC_GOT_DTPREL16_HI:
case BFD_RELOC_PPC_GOT_DTPREL16_HA:
case BFD_RELOC_PPC_GOT_TPREL16:
case BFD_RELOC_PPC_GOT_TPREL16_LO:
case BFD_RELOC_PPC_GOT_TPREL16_HI:
case BFD_RELOC_PPC_GOT_TPREL16_HA:
as_bad (_("symbol+offset not supported for got tls"));
break;
}
}
/* Now check for identifier@suffix+constant. */
if (*str == '-' || *str == '+')
@ -2797,108 +2822,156 @@ md_assemble (char *str)
ppc_cpu, (char *) NULL, 0);
}
#ifdef OBJ_ELF
else if ((reloc = ppc_elf_suffix (&str, &ex)) != BFD_RELOC_UNUSED)
else
{
/* Some TLS tweaks. */
switch (reloc)
if (ex.X_op == O_symbol && str[0] == '(')
{
default:
break;
case BFD_RELOC_PPC_TLS:
insn = ppc_insert_operand (insn, operand, ppc_obj64 ? 13 : 2,
ppc_cpu, (char *) NULL, 0);
break;
/* We'll only use the 32 (or 64) bit form of these relocations
in constants. Instructions get the 16 bit form. */
case BFD_RELOC_PPC_DTPREL:
reloc = BFD_RELOC_PPC_DTPREL16;
break;
case BFD_RELOC_PPC_TPREL:
reloc = BFD_RELOC_PPC_TPREL16;
break;
}
const char *sym_name = S_GET_NAME (ex.X_add_symbol);
if (sym_name[0] == '.')
++sym_name;
/* For the absolute forms of branches, convert the PC
relative form back into the absolute. */
if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
{
switch (reloc)
if (strcasecmp (sym_name, "__tls_get_addr") == 0)
{
case BFD_RELOC_PPC_B26:
reloc = BFD_RELOC_PPC_BA26;
break;
case BFD_RELOC_PPC_B16:
reloc = BFD_RELOC_PPC_BA16;
break;
case BFD_RELOC_PPC_B16_BRTAKEN:
reloc = BFD_RELOC_PPC_BA16_BRTAKEN;
break;
case BFD_RELOC_PPC_B16_BRNTAKEN:
reloc = BFD_RELOC_PPC_BA16_BRNTAKEN;
break;
default:
break;
expressionS tls_exp;
hold = input_line_pointer;
input_line_pointer = str + 1;
expression (&tls_exp);
if (tls_exp.X_op == O_symbol)
{
reloc = BFD_RELOC_UNUSED;
if (strncasecmp (input_line_pointer, "@tlsgd)", 7) == 0)
{
reloc = BFD_RELOC_PPC_TLSGD;
input_line_pointer += 7;
}
else if (strncasecmp (input_line_pointer, "@tlsld)", 7) == 0)
{
reloc = BFD_RELOC_PPC_TLSLD;
input_line_pointer += 7;
}
if (reloc != BFD_RELOC_UNUSED)
{
SKIP_WHITESPACE ();
str = input_line_pointer;
if (fc >= MAX_INSN_FIXUPS)
as_fatal (_("too many fixups"));
fixups[fc].exp = tls_exp;
fixups[fc].opindex = *opindex_ptr;
fixups[fc].reloc = reloc;
++fc;
}
}
input_line_pointer = hold;
}
}
if (ppc_obj64
&& (operand->flags & (PPC_OPERAND_DS | PPC_OPERAND_DQ)) != 0)
if ((reloc = ppc_elf_suffix (&str, &ex)) != BFD_RELOC_UNUSED)
{
/* Some TLS tweaks. */
switch (reloc)
{
case BFD_RELOC_16:
reloc = BFD_RELOC_PPC64_ADDR16_DS;
break;
case BFD_RELOC_LO16:
reloc = BFD_RELOC_PPC64_ADDR16_LO_DS;
break;
case BFD_RELOC_16_GOTOFF:
reloc = BFD_RELOC_PPC64_GOT16_DS;
break;
case BFD_RELOC_LO16_GOTOFF:
reloc = BFD_RELOC_PPC64_GOT16_LO_DS;
break;
case BFD_RELOC_LO16_PLTOFF:
reloc = BFD_RELOC_PPC64_PLT16_LO_DS;
break;
case BFD_RELOC_16_BASEREL:
reloc = BFD_RELOC_PPC64_SECTOFF_DS;
break;
case BFD_RELOC_LO16_BASEREL:
reloc = BFD_RELOC_PPC64_SECTOFF_LO_DS;
break;
case BFD_RELOC_PPC_TOC16:
reloc = BFD_RELOC_PPC64_TOC16_DS;
break;
case BFD_RELOC_PPC64_TOC16_LO:
reloc = BFD_RELOC_PPC64_TOC16_LO_DS;
break;
case BFD_RELOC_PPC64_PLTGOT16:
reloc = BFD_RELOC_PPC64_PLTGOT16_DS;
break;
case BFD_RELOC_PPC64_PLTGOT16_LO:
reloc = BFD_RELOC_PPC64_PLTGOT16_LO_DS;
break;
case BFD_RELOC_PPC_DTPREL16:
reloc = BFD_RELOC_PPC64_DTPREL16_DS;
break;
case BFD_RELOC_PPC_DTPREL16_LO:
reloc = BFD_RELOC_PPC64_DTPREL16_LO_DS;
break;
case BFD_RELOC_PPC_TPREL16:
reloc = BFD_RELOC_PPC64_TPREL16_DS;
break;
case BFD_RELOC_PPC_TPREL16_LO:
reloc = BFD_RELOC_PPC64_TPREL16_LO_DS;
break;
case BFD_RELOC_PPC_GOT_DTPREL16:
case BFD_RELOC_PPC_GOT_DTPREL16_LO:
case BFD_RELOC_PPC_GOT_TPREL16:
case BFD_RELOC_PPC_GOT_TPREL16_LO:
break;
default:
as_bad (_("unsupported relocation for DS offset field"));
break;
case BFD_RELOC_PPC_TLS:
insn = ppc_insert_operand (insn, operand, ppc_obj64 ? 13 : 2,
ppc_cpu, (char *) NULL, 0);
break;
/* We'll only use the 32 (or 64) bit form of these relocations
in constants. Instructions get the 16 bit form. */
case BFD_RELOC_PPC_DTPREL:
reloc = BFD_RELOC_PPC_DTPREL16;
break;
case BFD_RELOC_PPC_TPREL:
reloc = BFD_RELOC_PPC_TPREL16;
break;
}
/* For the absolute forms of branches, convert the PC
relative form back into the absolute. */
if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
{
switch (reloc)
{
case BFD_RELOC_PPC_B26:
reloc = BFD_RELOC_PPC_BA26;
break;
case BFD_RELOC_PPC_B16:
reloc = BFD_RELOC_PPC_BA16;
break;
case BFD_RELOC_PPC_B16_BRTAKEN:
reloc = BFD_RELOC_PPC_BA16_BRTAKEN;
break;
case BFD_RELOC_PPC_B16_BRNTAKEN:
reloc = BFD_RELOC_PPC_BA16_BRNTAKEN;
break;
default:
break;
}
}
if (ppc_obj64
&& (operand->flags & (PPC_OPERAND_DS | PPC_OPERAND_DQ)) != 0)
{
switch (reloc)
{
case BFD_RELOC_16:
reloc = BFD_RELOC_PPC64_ADDR16_DS;
break;
case BFD_RELOC_LO16:
reloc = BFD_RELOC_PPC64_ADDR16_LO_DS;
break;
case BFD_RELOC_16_GOTOFF:
reloc = BFD_RELOC_PPC64_GOT16_DS;
break;
case BFD_RELOC_LO16_GOTOFF:
reloc = BFD_RELOC_PPC64_GOT16_LO_DS;
break;
case BFD_RELOC_LO16_PLTOFF:
reloc = BFD_RELOC_PPC64_PLT16_LO_DS;
break;
case BFD_RELOC_16_BASEREL:
reloc = BFD_RELOC_PPC64_SECTOFF_DS;
break;
case BFD_RELOC_LO16_BASEREL:
reloc = BFD_RELOC_PPC64_SECTOFF_LO_DS;
break;
case BFD_RELOC_PPC_TOC16:
reloc = BFD_RELOC_PPC64_TOC16_DS;
break;
case BFD_RELOC_PPC64_TOC16_LO:
reloc = BFD_RELOC_PPC64_TOC16_LO_DS;
break;
case BFD_RELOC_PPC64_PLTGOT16:
reloc = BFD_RELOC_PPC64_PLTGOT16_DS;
break;
case BFD_RELOC_PPC64_PLTGOT16_LO:
reloc = BFD_RELOC_PPC64_PLTGOT16_LO_DS;
break;
case BFD_RELOC_PPC_DTPREL16:
reloc = BFD_RELOC_PPC64_DTPREL16_DS;
break;
case BFD_RELOC_PPC_DTPREL16_LO:
reloc = BFD_RELOC_PPC64_DTPREL16_LO_DS;
break;
case BFD_RELOC_PPC_TPREL16:
reloc = BFD_RELOC_PPC64_TPREL16_DS;
break;
case BFD_RELOC_PPC_TPREL16_LO:
reloc = BFD_RELOC_PPC64_TPREL16_LO_DS;
break;
case BFD_RELOC_PPC_GOT_DTPREL16:
case BFD_RELOC_PPC_GOT_DTPREL16_LO:
case BFD_RELOC_PPC_GOT_TPREL16:
case BFD_RELOC_PPC_GOT_TPREL16_LO:
break;
default:
as_bad (_("unsupported relocation for DS offset field"));
break;
}
}
}
@ -2906,12 +2979,11 @@ md_assemble (char *str)
if (fc >= MAX_INSN_FIXUPS)
as_fatal (_("too many fixups"));
fixups[fc].exp = ex;
fixups[fc].opindex = 0;
fixups[fc].opindex = *opindex_ptr;
fixups[fc].reloc = reloc;
++fc;
}
#endif /* OBJ_ELF */
#else /* OBJ_ELF */
else
{
/* We need to generate a fixup for this expression. */
@ -2922,6 +2994,7 @@ md_assemble (char *str)
fixups[fc].reloc = BFD_RELOC_UNUSED;
++fc;
}
#endif /* OBJ_ELF */
if (need_paren)
{
@ -3006,9 +3079,6 @@ md_assemble (char *str)
md_apply_fix. */
for (i = 0; i < fc; i++)
{
const struct powerpc_operand *operand;
operand = &powerpc_operands[fixups[i].opindex];
if (fixups[i].reloc != BFD_RELOC_UNUSED)
{
reloc_howto_type *reloc_howto;
@ -3055,13 +3125,18 @@ md_assemble (char *str)
}
}
else
fix_new_exp (frag_now,
f - frag_now->fr_literal,
4,
&fixups[i].exp,
(operand->flags & PPC_OPERAND_RELATIVE) != 0,
((bfd_reloc_code_real_type)
(fixups[i].opindex + (int) BFD_RELOC_UNUSED)));
{
const struct powerpc_operand *operand;
operand = &powerpc_operands[fixups[i].opindex];
fix_new_exp (frag_now,
f - frag_now->fr_literal,
4,
&fixups[i].exp,
(operand->flags & PPC_OPERAND_RELATIVE) != 0,
((bfd_reloc_code_real_type)
(fixups[i].opindex + (int) BFD_RELOC_UNUSED)));
}
}
}
@ -6155,6 +6230,8 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
break;
case BFD_RELOC_PPC_TLS:
case BFD_RELOC_PPC_TLSGD:
case BFD_RELOC_PPC_TLSLD:
break;
case BFD_RELOC_PPC_DTPMOD:

View File

@ -1,3 +1,8 @@
2009-03-04 Alan Modra <amodra@bigpond.net.au>
* ppc.h (R_PPC_TLSGD, R_PPC_TLSLD): Add new relocs.
* ppc64.h (R_PPC64_TLSGD, R_PPC64_TLSLD): Add new relocs.
2009-03-02 Qinwei <qinwei@sunnorth.com.cn>
* score.h (RELOC_NUMBER): Add R_SCORE_IMM32.

View File

@ -1,6 +1,6 @@
/* PPC ELF support for BFD.
Copyright 1995, 1996, 1998, 2000, 2001, 2002, 2003, 2005, 2007, 2008
Free Software Foundation, Inc.
Copyright 1995, 1996, 1998, 2000, 2001, 2002, 2003, 2005, 2007, 2008,
2009 Free Software Foundation, Inc.
By Michael Meissner, Cygnus Support, <meissner@cygnus.com>, from information
in the System V Application Binary Interface, PowerPC Processor Supplement
@ -100,6 +100,8 @@ START_RELOC_NUMBERS (elf_ppc_reloc_type)
RELOC_NUMBER (R_PPC_GOT_DTPREL16_LO, 92)
RELOC_NUMBER (R_PPC_GOT_DTPREL16_HI, 93)
RELOC_NUMBER (R_PPC_GOT_DTPREL16_HA, 94)
RELOC_NUMBER (R_PPC_TLSGD, 95)
RELOC_NUMBER (R_PPC_TLSLD, 96)
/* The remaining relocs are from the Embedded ELF ABI, and are not
in the SVR4 ELF ABI. */

View File

@ -1,5 +1,5 @@
/* PPC64 ELF support for BFD.
Copyright 2003 Free Software Foundation, Inc.
Copyright 2003, 2005, 2009 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
@ -136,6 +136,8 @@ START_RELOC_NUMBERS (elf_ppc64_reloc_type)
RELOC_NUMBER (R_PPC64_DTPREL16_HIGHERA, 104)
RELOC_NUMBER (R_PPC64_DTPREL16_HIGHEST, 105)
RELOC_NUMBER (R_PPC64_DTPREL16_HIGHESTA, 106)
RELOC_NUMBER (R_PPC64_TLSGD, 107)
RELOC_NUMBER (R_PPC64_TLSLD, 108)
/* These are GNU extensions to enable C++ vtable garbage collection. */
RELOC_NUMBER (R_PPC64_GNU_VTINHERIT, 253)

View File

@ -1,3 +1,9 @@
2009-03-04 Alan Modra <amodra@bigpond.net.au>
* ld-powerpc/tlsmark.s, * ld-powerpc/tlsmark.d: New test.
* ld-powerpc/tlsmark32.s, * ld-powerpc/tlsmark32.d: New test.
* ld-powerpc/powerpc.exp: Run them.
2009-03-02 Sebastian Huber <sebastian.huber@embedded-brains.de>
* ld-scripts/regions-alias-1.t: New file.

View File

@ -1,5 +1,5 @@
# Expect script for ld-powerpc tests
# Copyright 2002, 2003, 2005, 2006, 2007, 2008 Free Software Foundation
# Copyright 2002, 2003, 2005, 2006, 2007, 2008, 2009 Free Software Foundation
#
# This file is part of the GNU Binutils.
#
@ -112,6 +112,9 @@ set ppcelftests {
{{readelf -WSsrl tlsso32.r} {objdump -dr tlsso32.d}
{objdump -sj.got tlsso32.g} {objdump -sj.tdata tlsso32.t}}
"tls32.so"}
{"TLS32 markers" "-melf32ppc" "-a32" {tlsmark32.s tlslib32.s}
{{objdump -dr tlsmark32.d}}
"tlsmark32"}
{"Shared library with global symbol" "-shared -melf32ppc" "-a32" {sdalib.s}
{} "sdalib.so"}
{"Dynamic application with SDA" "-melf32ppc tmpdir/sdalib.so" "-a32" {sdadyn.s}
@ -145,6 +148,9 @@ set ppc64elftests {
{{readelf -WSsrl tlstocso.r} {objdump -dr tlstocso.d}
{objdump -sj.got tlstocso.g} {objdump -sj.tdata tlstocso.t}}
"tlstoc.so"}
{"TLS markers" "-melf64ppc" "-a64" {tlsmark.s tlslib.s}
{{objdump -dr tlsmark.d}}
"tlsmark"}
{"sym@tocbase" "-shared -melf64ppc" "-a64" {symtocbase-1.s symtocbase-2.s}
{{objdump -dj.data symtocbase.d}} "symtocbase.so"}
}

View File

@ -0,0 +1,42 @@
#source: tlsmark.s
#source: tlslib.s
#as: -a64
#ld: -melf64ppc
#objdump: -dr
#target: powerpc64*-*-*
.*: +file format elf64-powerpc
Disassembly of section \.text:
0+100000e8 <_start>:
100000e8: 48 00 00 18 b 10000100 <_start\+0x18>
100000ec: 60 00 00 00 nop
100000f0: 38 63 90 00 addi r3,r3,-28672
100000f4: e8 83 00 00 ld r4,0\(r3\)
100000f8: 3c 6d 00 00 addis r3,r13,0
100000fc: 48 00 00 0c b 10000108 <_start\+0x20>
10000100: 3c 6d 00 00 addis r3,r13,0
10000104: 4b ff ff e8 b 100000ec <_start\+0x4>
10000108: 60 00 00 00 nop
1000010c: 38 63 10 00 addi r3,r3,4096
10000110: e8 83 80 00 ld r4,-32768\(r3\)
10000114: 3c 6d 00 00 addis r3,r13,0
10000118: 48 00 00 0c b 10000124 <_start\+0x3c>
1000011c: 3c 6d 00 00 addis r3,r13,0
10000120: 48 00 00 14 b 10000134 <_start\+0x4c>
10000124: 60 00 00 00 nop
10000128: 38 63 90 04 addi r3,r3,-28668
1000012c: e8 a3 00 00 ld r5,0\(r3\)
10000130: 4b ff ff ec b 1000011c <_start\+0x34>
10000134: 60 00 00 00 nop
10000138: 38 63 10 00 addi r3,r3,4096
1000013c: e8 a3 80 04 ld r5,-32764\(r3\)
10000140: 38 62 80 28 addi r3,r2,-32728
10000144: 3f a0 10 01 lis r29,4097
10000148: 3b bd 01 68 addi r29,r29,360
1000014c: 48 00 00 09 bl 10000154 <\.__tls_get_addr>
10000150: 60 00 00 00 nop
0+10000154 <\.__tls_get_addr>:
10000154: 4e 80 00 20 blr

View File

@ -0,0 +1,55 @@
.section ".tdata","awT",@progbits
x: .int 1
y: .int 2
.section ".toc","aw",@progbits
.p2align 3
.LC0:
.quad y@dtpmod
.quad y@dtprel
.LC1:
.quad y@dtpmod
.quad 0
.text
.global _start
_start:
b .L2
.L1:
bl __tls_get_addr(x@tlsgd)
nop
ld 4,0(3)
addi 3,2,x@got@tlsld
b .L3
.L2:
addi 3,2,x@got@tlsgd
b .L1
.L3:
bl __tls_get_addr(x@tlsld)
nop
ld 4,x@dtprel(3)
addi 3,2,.LC0@toc
b .L5
.L4:
addi 3,2,.LC1@toc
b .L6
.L5:
bl .__tls_get_addr(.LC0@tlsgd)
nop
ld 5,0(3)
b .L4
.L6:
bl .__tls_get_addr(.LC1@tlsld)
nop
ld 5,y@dtprel(3)
.section ".text.no","ax",@progbits
.p2align 2
addi 3,2,gd@got@tlsgd
lis 29,__tls_get_addr@ha
addi 29,29,__tls_get_addr@l
bl __tls_get_addr
nop

View File

@ -0,0 +1,29 @@
#source: tlsmark32.s
#source: tlslib32.s
#as: -a32
#ld: -melf32ppc
#objdump: -dr
#target: powerpc*-*-*
.*: file format elf32-powerpc
Disassembly of section \.text:
0+1800094 <_start>:
1800094: 48 00 00 14 b 18000a8 <_start\+0x14>
1800098: 38 63 90 00 addi r3,r3,-28672
180009c: 80 83 00 00 lwz r4,0\(r3\)
18000a0: 3c 62 00 00 addis r3,r2,0
18000a4: 48 00 00 0c b 18000b0 <_start\+0x1c>
18000a8: 3c 62 00 00 addis r3,r2,0
18000ac: 4b ff ff ec b 1800098 <_start\+0x4>
18000b0: 38 63 10 00 addi r3,r3,4096
18000b4: 80 83 80 00 lwz r4,-32768\(r3\)
18000b8: 38 7f ff f4 addi r3,r31,-12
18000bc: 3f a0 01 80 lis r29,384
18000c0: 3b bd 00 c8 addi r29,r29,200
18000c4: 48 00 00 05 bl 18000c8 <__tls_get_addr>
0+18000c8 <__tls_get_addr>:
18000c8: 4e 80 00 20 blr
#pass

View File

@ -0,0 +1,27 @@
.section ".tdata","awT",@progbits
x: .int 1
.text
.global _start
_start:
b .L2
.L1:
bl __tls_get_addr(x@tlsgd)
lwz 4,0(3)
addi 3,31,x@got@tlsld
b .L3
.L2:
addi 3,31,x@got@tlsgd
b .L1
.L3:
bl __tls_get_addr(x@tlsld)
lwz 4,x@dtprel(3)
.section ".text.no","ax",@progbits
.p2align 2
addi 3,31,gd@got@tlsgd
lis 29,__tls_get_addr@ha
addi 29,29,__tls_get_addr@l
bl __tls_get_addr