Add new PowerPC relocations to binutils
Summary: LLVM/Clang generates relocations that our binutils doesn't understand, but newer binutils does. I got permission from the author of a series of patches to relicense them as GPLv2 for use in FreeBSD. The upstream git hashes are: ac2df442ac7901f00af15b272fc48b594b433713 2b95367962dc14f69d3c338c4d54195266e2e169 102890f04c44b64cf5cef4588267dd9f24086ac7 b7fcf6f6bb53b5027e111107f5416769cb9a5798 1d483afedd5a628dc84fb58d1d570f79fdfbfa7b 90aecf7a80c1cefeb45fc10a6cd02c8338e34b4c 3a71aa26df2a372a58e9c11ef9ba51fd0e83320a 727fc41e077139570ea8b8ddfd6c546b2a55627c With the import of clang 3.5, and a few backported patches, we should be able to move powerpc and powerpc64 to clang-as-cc soon. Test Plan: Passes make tinderbox, so no regressions. Binaries built with clang run on powerpc64. Reviewers: #committers, dim Reviewed By: dim Differential Revision: https://reviews.freebsd.org/D1297 Obtained from: Alan Modra, upstream binutils-gdb git MFC after: 3 weeks Relnotes: yes
This commit is contained in:
parent
44eb8bbe7b
commit
ff0bab9760
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=275718
@ -1,3 +1,49 @@
|
|||||||
|
2009-02-15 Alan Modra <amodra@bigpond.net.au>
|
||||||
|
|
||||||
|
* elf64-ppc.c (struct _ppc64_elf_section_data): Delete t_symndx,
|
||||||
|
add toc.symndx and toc.add.
|
||||||
|
(ppc64_elf_check_relocs): Don't set htab->tls_get_addr here.
|
||||||
|
Set up toc.add.
|
||||||
|
(get_tls_mask): Add toc_addend param, set from toc.add. Adjust all
|
||||||
|
callers.
|
||||||
|
(ppc64_elf_tls_setup): Set htab->tls_get_addr and tls_get_addr_fd.
|
||||||
|
(branch_reloc_hash_match): New function, extracted from..
|
||||||
|
(ppc64_elf_tls_optimize): ..here.
|
||||||
|
(ppc64_elf_relocate_section): Properly set addends when optimizing
|
||||||
|
tls sequences. Avoid unnecessary reading and writing of insns.
|
||||||
|
Only redo reloc when symbol changed. Bypass symbol checks when
|
||||||
|
using tlsld_got.
|
||||||
|
* elf32-ppc.c (ppc_elf_tls_setup): Correct comment.
|
||||||
|
(branch_reloc_hash_match): New function, extracted from..
|
||||||
|
(ppc_elf_tls_optimize): ..here.
|
||||||
|
(ppc_elf_relocate_section): Avoid unnecessary reading of insns.
|
||||||
|
Don't clear addend on zapped __tls_get_addr reloc.
|
||||||
|
|
||||||
|
2008-08-11 Alan Modra <amodra@bigpond.net.au>
|
||||||
|
|
||||||
|
* elf64-ppc.c (toc_adjusting_stub_needed): Any call via the plt
|
||||||
|
needs r2 valid, not just those to external syms.
|
||||||
|
|
||||||
|
2007-11-06 Alan Modra <amodra@bigpond.net.au>
|
||||||
|
|
||||||
|
* elf32-ppc.c (ppc_elf_check_relocs): Don't refcount tlsld_got here..
|
||||||
|
(ppc_elf_gc_sweep_hook): ..or here..
|
||||||
|
(ppc_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.
|
||||||
|
(ppc_elf_size_dynamic_sections): Call allocate_dynrelocs before
|
||||||
|
allocating tlsld_got.
|
||||||
|
(ppc_elf_relocate_section): Remove check that a tls_get_addr
|
||||||
|
call follows gd and ld relocs.
|
||||||
|
|
||||||
|
2007-08-13 Alan Modra <amodra@bigpond.net.au>
|
||||||
|
|
||||||
|
* elf64-ppc.c (ADDI_R12_R12, LD_R11_0R2, LD_R2_0R2): Define.
|
||||||
|
Update stub comments.
|
||||||
|
(build_plt_stub): Build two variants, one without "addis".
|
||||||
|
(ppc_build_one_stub): Build stubs without "addis" if possible.
|
||||||
|
(ppc_size_one_stub): Size new stubs.
|
||||||
|
|
||||||
2007-07-02 Joseph Myers <joseph@codesourcery.com>
|
2007-07-02 Joseph Myers <joseph@codesourcery.com>
|
||||||
|
|
||||||
* elfxx-mips.c (mips_elf_calculate_relocation): Handle
|
* elfxx-mips.c (mips_elf_calculate_relocation): Handle
|
||||||
|
@ -1380,6 +1380,9 @@ typedef struct bfd_section
|
|||||||
/* Nonzero if this section has TLS related relocations. */
|
/* Nonzero if this section has TLS related relocations. */
|
||||||
unsigned int has_tls_reloc:1;
|
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. */
|
/* Nonzero if this section has a gp reloc. */
|
||||||
unsigned int has_gp_reloc:1;
|
unsigned int has_gp_reloc:1;
|
||||||
|
|
||||||
@ -1640,11 +1643,11 @@ extern asection bfd_ind_section;
|
|||||||
/* segment_mark, sec_info_type, use_rela_p, has_tls_reloc, */ \
|
/* segment_mark, sec_info_type, use_rela_p, has_tls_reloc, */ \
|
||||||
0, 0, 0, 0, \
|
0, 0, 0, 0, \
|
||||||
\
|
\
|
||||||
/* has_gp_reloc, need_finalize_relax, reloc_done, */ \
|
/* has_tls_get_addr_call, has_gp_reloc, need_finalize_relax, */ \
|
||||||
0, 0, 0, \
|
0, 0, 0, \
|
||||||
\
|
\
|
||||||
/* vma, lma, size, rawsize */ \
|
/* reloc_done, vma, lma, size, rawsize */ \
|
||||||
0, 0, 0, 0, \
|
0, 0, 0, 0, 0, \
|
||||||
\
|
\
|
||||||
/* output_offset, output_section, alignment_power, */ \
|
/* output_offset, output_section, alignment_power, */ \
|
||||||
0, (struct bfd_section *) &SEC, 0, \
|
0, (struct bfd_section *) &SEC, 0, \
|
||||||
@ -2896,6 +2899,8 @@ in the instruction. */
|
|||||||
|
|
||||||
/* PowerPC and PowerPC64 thread-local storage relocations. */
|
/* PowerPC and PowerPC64 thread-local storage relocations. */
|
||||||
BFD_RELOC_PPC_TLS,
|
BFD_RELOC_PPC_TLS,
|
||||||
|
BFD_RELOC_PPC_TLSGD,
|
||||||
|
BFD_RELOC_PPC_TLSLD,
|
||||||
BFD_RELOC_PPC_DTPMOD,
|
BFD_RELOC_PPC_DTPMOD,
|
||||||
BFD_RELOC_PPC_TPREL16,
|
BFD_RELOC_PPC_TPREL16,
|
||||||
BFD_RELOC_PPC_TPREL16_LO,
|
BFD_RELOC_PPC_TPREL16_LO,
|
||||||
|
@ -58,10 +58,10 @@ static asection bfd_debug_section =
|
|||||||
0, 0, 1, 0,
|
0, 0, 1, 0,
|
||||||
/* segment_mark, sec_info_type, use_rela_p, has_tls_reloc, */
|
/* segment_mark, sec_info_type, use_rela_p, has_tls_reloc, */
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
/* has_gp_reloc, need_finalize_relax, reloc_done, */
|
/* has_tls_get_addr_call, has_gp_reloc, need_finalize_relax, */
|
||||||
0, 0, 0,
|
0, 0, 0,
|
||||||
/* vma, lma, size, rawsize, */
|
/* reloc_done, vma, lma, size, rawsize, */
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0, 0,
|
||||||
/* output_offset, output_section, alignment_power, */
|
/* output_offset, output_section, alignment_power, */
|
||||||
0, NULL, 0,
|
0, NULL, 0,
|
||||||
/* relocation, orelocation, reloc_count, filepos, rel_filepos, */
|
/* relocation, orelocation, reloc_count, filepos, rel_filepos, */
|
||||||
|
@ -746,7 +746,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
|
|||||||
0xffff, /* dst_mask */
|
0xffff, /* dst_mask */
|
||||||
FALSE), /* pcrel_offset */
|
FALSE), /* pcrel_offset */
|
||||||
|
|
||||||
/* Marker reloc for TLS. */
|
/* Marker relocs for TLS. */
|
||||||
HOWTO (R_PPC_TLS,
|
HOWTO (R_PPC_TLS,
|
||||||
0, /* rightshift */
|
0, /* rightshift */
|
||||||
2, /* size (0 = byte, 1 = short, 2 = long) */
|
2, /* size (0 = byte, 1 = short, 2 = long) */
|
||||||
@ -761,6 +761,34 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
|
|||||||
0, /* dst_mask */
|
0, /* dst_mask */
|
||||||
FALSE), /* pcrel_offset */
|
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
|
/* Computes the load module index of the load module that contains the
|
||||||
definition of its TLS sym. */
|
definition of its TLS sym. */
|
||||||
HOWTO (R_PPC_DTPMOD32,
|
HOWTO (R_PPC_DTPMOD32,
|
||||||
@ -1524,6 +1552,8 @@ ppc_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
|
|||||||
case BFD_RELOC_CTOR: r = R_PPC_ADDR32; break;
|
case BFD_RELOC_CTOR: r = R_PPC_ADDR32; break;
|
||||||
case BFD_RELOC_PPC_TOC16: r = R_PPC_TOC16; 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_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_DTPMOD: r = R_PPC_DTPMOD32; break;
|
||||||
case BFD_RELOC_PPC_TPREL16: r = R_PPC_TPREL16; break;
|
case BFD_RELOC_PPC_TPREL16: r = R_PPC_TPREL16; break;
|
||||||
case BFD_RELOC_PPC_TPREL16_LO: r = R_PPC_TPREL16_LO; break;
|
case BFD_RELOC_PPC_TPREL16_LO: r = R_PPC_TPREL16_LO; break;
|
||||||
@ -2345,16 +2375,34 @@ struct plt_entry
|
|||||||
bfd_vma glink_offset;
|
bfd_vma glink_offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Of those relocs that might be copied as dynamic relocs, this macro
|
/* Of those relocs that might be copied as dynamic relocs, this function
|
||||||
selects those that must be copied when linking a shared library,
|
selects those that must be copied when linking a shared library,
|
||||||
even when the symbol is local. */
|
even when the symbol is local. */
|
||||||
|
|
||||||
#define MUST_BE_DYN_RELOC(RTYPE) \
|
static int
|
||||||
((RTYPE) != R_PPC_REL24 \
|
must_be_dyn_reloc (struct bfd_link_info *info,
|
||||||
&& (RTYPE) != R_PPC_REL14 \
|
enum elf_ppc_reloc_type r_type)
|
||||||
&& (RTYPE) != R_PPC_REL14_BRTAKEN \
|
{
|
||||||
&& (RTYPE) != R_PPC_REL14_BRNTAKEN \
|
switch (r_type)
|
||||||
&& (RTYPE) != R_PPC_REL32)
|
{
|
||||||
|
default:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case R_PPC_REL24:
|
||||||
|
case R_PPC_REL14:
|
||||||
|
case R_PPC_REL14_BRTAKEN:
|
||||||
|
case R_PPC_REL14_BRNTAKEN:
|
||||||
|
case R_PPC_REL32:
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case R_PPC_TPREL32:
|
||||||
|
case R_PPC_TPREL16:
|
||||||
|
case R_PPC_TPREL16_LO:
|
||||||
|
case R_PPC_TPREL16_HI:
|
||||||
|
case R_PPC_TPREL16_HA:
|
||||||
|
return !info->executable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* If ELIMINATE_COPY_RELOCS is non-zero, the linker will try to avoid
|
/* If ELIMINATE_COPY_RELOCS is non-zero, the linker will try to avoid
|
||||||
copying dynamic variables from a shared lib into an app's dynbss
|
copying dynamic variables from a shared lib into an app's dynbss
|
||||||
@ -2421,7 +2469,7 @@ struct ppc_elf_link_hash_table
|
|||||||
/* The .got.plt section (VxWorks only)*/
|
/* The .got.plt section (VxWorks only)*/
|
||||||
asection *sgotplt;
|
asection *sgotplt;
|
||||||
|
|
||||||
/* Shortcut to .__tls_get_addr. */
|
/* Shortcut to __tls_get_addr. */
|
||||||
struct elf_link_hash_entry *tls_get_addr;
|
struct elf_link_hash_entry *tls_get_addr;
|
||||||
|
|
||||||
/* The bfd that forced an old-style PLT. */
|
/* The bfd that forced an old-style PLT. */
|
||||||
@ -3040,6 +3088,7 @@ ppc_elf_check_relocs (bfd *abfd,
|
|||||||
const Elf_Internal_Rela *rel;
|
const Elf_Internal_Rela *rel;
|
||||||
const Elf_Internal_Rela *rel_end;
|
const Elf_Internal_Rela *rel_end;
|
||||||
asection *got2, *sreloc;
|
asection *got2, *sreloc;
|
||||||
|
struct elf_link_hash_entry *tga;
|
||||||
|
|
||||||
if (info->relocatable)
|
if (info->relocatable)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -3063,6 +3112,8 @@ ppc_elf_check_relocs (bfd *abfd,
|
|||||||
ppc_elf_howto_init ();
|
ppc_elf_howto_init ();
|
||||||
|
|
||||||
htab = ppc_elf_hash_table (info);
|
htab = ppc_elf_hash_table (info);
|
||||||
|
tga = elf_link_hash_lookup (&htab->elf, "__tls_get_addr",
|
||||||
|
FALSE, FALSE, TRUE);
|
||||||
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
|
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
|
||||||
sym_hashes = elf_sym_hashes (abfd);
|
sym_hashes = elf_sym_hashes (abfd);
|
||||||
got2 = bfd_get_section_by_name (abfd, ".got2");
|
got2 = bfd_get_section_by_name (abfd, ".got2");
|
||||||
@ -3074,7 +3125,7 @@ ppc_elf_check_relocs (bfd *abfd,
|
|||||||
unsigned long r_symndx;
|
unsigned long r_symndx;
|
||||||
enum elf_ppc_reloc_type r_type;
|
enum elf_ppc_reloc_type r_type;
|
||||||
struct elf_link_hash_entry *h;
|
struct elf_link_hash_entry *h;
|
||||||
int tls_type = 0;
|
int tls_type;
|
||||||
|
|
||||||
r_symndx = ELF32_R_SYM (rel->r_info);
|
r_symndx = ELF32_R_SYM (rel->r_info);
|
||||||
if (r_symndx < symtab_hdr->sh_info)
|
if (r_symndx < symtab_hdr->sh_info)
|
||||||
@ -3101,14 +3152,48 @@ ppc_elf_check_relocs (bfd *abfd,
|
|||||||
BFD_ASSERT (h == htab->elf.hgot);
|
BFD_ASSERT (h == htab->elf.hgot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tls_type = 0;
|
||||||
r_type = ELF32_R_TYPE (rel->r_info);
|
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)
|
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:
|
||||||
case R_PPC_GOT_TLSLD16_LO:
|
case R_PPC_GOT_TLSLD16_LO:
|
||||||
case R_PPC_GOT_TLSLD16_HI:
|
case R_PPC_GOT_TLSLD16_HI:
|
||||||
case R_PPC_GOT_TLSLD16_HA:
|
case R_PPC_GOT_TLSLD16_HA:
|
||||||
htab->tlsld_got.refcount += 1;
|
|
||||||
tls_type = TLS_TLS | TLS_LD;
|
tls_type = TLS_TLS | TLS_LD;
|
||||||
goto dogottls;
|
goto dogottls;
|
||||||
|
|
||||||
@ -3123,7 +3208,7 @@ ppc_elf_check_relocs (bfd *abfd,
|
|||||||
case R_PPC_GOT_TPREL16_LO:
|
case R_PPC_GOT_TPREL16_LO:
|
||||||
case R_PPC_GOT_TPREL16_HI:
|
case R_PPC_GOT_TPREL16_HI:
|
||||||
case R_PPC_GOT_TPREL16_HA:
|
case R_PPC_GOT_TPREL16_HA:
|
||||||
if (info->shared)
|
if (!info->executable)
|
||||||
info->flags |= DF_STATIC_TLS;
|
info->flags |= DF_STATIC_TLS;
|
||||||
tls_type = TLS_TLS | TLS_TPREL;
|
tls_type = TLS_TLS | TLS_TPREL;
|
||||||
goto dogottls;
|
goto dogottls;
|
||||||
@ -3358,7 +3443,7 @@ ppc_elf_check_relocs (bfd *abfd,
|
|||||||
|
|
||||||
/* This refers only to functions defined in the shared library. */
|
/* This refers only to functions defined in the shared library. */
|
||||||
case R_PPC_LOCAL24PC:
|
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->plt_type = PLT_OLD;
|
||||||
htab->old_bfd = abfd;
|
htab->old_bfd = abfd;
|
||||||
@ -3381,7 +3466,11 @@ ppc_elf_check_relocs (bfd *abfd,
|
|||||||
|
|
||||||
/* We shouldn't really be seeing these. */
|
/* We shouldn't really be seeing these. */
|
||||||
case R_PPC_TPREL32:
|
case R_PPC_TPREL32:
|
||||||
if (info->shared)
|
case R_PPC_TPREL16:
|
||||||
|
case R_PPC_TPREL16_LO:
|
||||||
|
case R_PPC_TPREL16_HI:
|
||||||
|
case R_PPC_TPREL16_HA:
|
||||||
|
if (!info->executable)
|
||||||
info->flags |= DF_STATIC_TLS;
|
info->flags |= DF_STATIC_TLS;
|
||||||
goto dodyn;
|
goto dodyn;
|
||||||
|
|
||||||
@ -3390,14 +3479,6 @@ ppc_elf_check_relocs (bfd *abfd,
|
|||||||
case R_PPC_DTPREL32:
|
case R_PPC_DTPREL32:
|
||||||
goto dodyn;
|
goto dodyn;
|
||||||
|
|
||||||
case R_PPC_TPREL16:
|
|
||||||
case R_PPC_TPREL16_LO:
|
|
||||||
case R_PPC_TPREL16_HI:
|
|
||||||
case R_PPC_TPREL16_HA:
|
|
||||||
if (info->shared)
|
|
||||||
info->flags |= DF_STATIC_TLS;
|
|
||||||
goto dodyn;
|
|
||||||
|
|
||||||
case R_PPC_REL32:
|
case R_PPC_REL32:
|
||||||
if (h == NULL
|
if (h == NULL
|
||||||
&& got2 != NULL
|
&& got2 != NULL
|
||||||
@ -3488,7 +3569,7 @@ ppc_elf_check_relocs (bfd *abfd,
|
|||||||
dynamic library if we manage to avoid copy relocs for the
|
dynamic library if we manage to avoid copy relocs for the
|
||||||
symbol. */
|
symbol. */
|
||||||
if ((info->shared
|
if ((info->shared
|
||||||
&& (MUST_BE_DYN_RELOC (r_type)
|
&& (must_be_dyn_reloc (info, r_type)
|
||||||
|| (h != NULL
|
|| (h != NULL
|
||||||
&& (! info->symbolic
|
&& (! info->symbolic
|
||||||
|| h->root.type == bfd_link_hash_defweak
|
|| h->root.type == bfd_link_hash_defweak
|
||||||
@ -3583,7 +3664,7 @@ ppc_elf_check_relocs (bfd *abfd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
p->count += 1;
|
p->count += 1;
|
||||||
if (!MUST_BE_DYN_RELOC (r_type))
|
if (!must_be_dyn_reloc (info, r_type))
|
||||||
p->pc_count += 1;
|
p->pc_count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3903,9 +3984,6 @@ ppc_elf_gc_sweep_hook (bfd *abfd,
|
|||||||
case R_PPC_GOT_TLSLD16_LO:
|
case R_PPC_GOT_TLSLD16_LO:
|
||||||
case R_PPC_GOT_TLSLD16_HI:
|
case R_PPC_GOT_TLSLD16_HI:
|
||||||
case R_PPC_GOT_TLSLD16_HA:
|
case R_PPC_GOT_TLSLD16_HA:
|
||||||
htab->tlsld_got.refcount -= 1;
|
|
||||||
/* Fall thru */
|
|
||||||
|
|
||||||
case R_PPC_GOT_TLSGD16:
|
case R_PPC_GOT_TLSGD16:
|
||||||
case R_PPC_GOT_TLSGD16_LO:
|
case R_PPC_GOT_TLSGD16_LO:
|
||||||
case R_PPC_GOT_TLSGD16_HI:
|
case R_PPC_GOT_TLSGD16_HI:
|
||||||
@ -3979,7 +4057,8 @@ ppc_elf_gc_sweep_hook (bfd *abfd,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set htab->tls_get_addr and call the generic ELF tls_setup function. */
|
/* Set plt output section type, htab->tls_get_addr, and call the
|
||||||
|
generic ELF tls_setup function. */
|
||||||
|
|
||||||
asection *
|
asection *
|
||||||
ppc_elf_tls_setup (bfd *obfd, struct bfd_link_info *info)
|
ppc_elf_tls_setup (bfd *obfd, struct bfd_link_info *info)
|
||||||
@ -4000,6 +4079,43 @@ ppc_elf_tls_setup (bfd *obfd, struct bfd_link_info *info)
|
|||||||
return _bfd_elf_tls_setup (obfd, info);
|
return _bfd_elf_tls_setup (obfd, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return TRUE iff REL is a branch reloc with a global symbol matching
|
||||||
|
HASH. */
|
||||||
|
|
||||||
|
static bfd_boolean
|
||||||
|
branch_reloc_hash_match (const bfd *ibfd,
|
||||||
|
const Elf_Internal_Rela *rel,
|
||||||
|
const struct elf_link_hash_entry *hash)
|
||||||
|
{
|
||||||
|
Elf_Internal_Shdr *symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
|
||||||
|
enum elf_ppc_reloc_type r_type = ELF32_R_TYPE (rel->r_info);
|
||||||
|
unsigned int r_symndx = ELF32_R_SYM (rel->r_info);
|
||||||
|
|
||||||
|
if (r_symndx >= symtab_hdr->sh_info
|
||||||
|
&& (r_type == R_PPC_PLTREL24
|
||||||
|
|| r_type == R_PPC_LOCAL24PC
|
||||||
|
|| r_type == R_PPC_REL14
|
||||||
|
|| r_type == R_PPC_REL14_BRTAKEN
|
||||||
|
|| r_type == R_PPC_REL14_BRNTAKEN
|
||||||
|
|| r_type == R_PPC_REL24
|
||||||
|
|| r_type == R_PPC_ADDR24
|
||||||
|
|| r_type == R_PPC_ADDR14
|
||||||
|
|| r_type == R_PPC_ADDR14_BRTAKEN
|
||||||
|
|| r_type == R_PPC_ADDR14_BRNTAKEN))
|
||||||
|
{
|
||||||
|
struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (ibfd);
|
||||||
|
struct elf_link_hash_entry *h;
|
||||||
|
|
||||||
|
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
|
||||||
|
while (h->root.type == bfd_link_hash_indirect
|
||||||
|
|| h->root.type == bfd_link_hash_warning)
|
||||||
|
h = (struct elf_link_hash_entry *) h->root.u.i.link;
|
||||||
|
if (h == hash)
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Run through all the TLS relocs looking for optimization
|
/* Run through all the TLS relocs looking for optimization
|
||||||
opportunities. */
|
opportunities. */
|
||||||
|
|
||||||
@ -4010,187 +4126,204 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED,
|
|||||||
bfd *ibfd;
|
bfd *ibfd;
|
||||||
asection *sec;
|
asection *sec;
|
||||||
struct ppc_elf_link_hash_table *htab;
|
struct ppc_elf_link_hash_table *htab;
|
||||||
|
int pass;
|
||||||
|
|
||||||
if (info->relocatable || info->shared)
|
if (info->relocatable || !info->executable)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
htab = ppc_elf_hash_table (info);
|
htab = ppc_elf_hash_table (info);
|
||||||
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
|
/* Make two passes through the relocs. First time check that tls
|
||||||
{
|
relocs involved in setting up a tls_get_addr call are indeed
|
||||||
Elf_Internal_Sym *locsyms = NULL;
|
followed by such a call. If they are not, exclude them from
|
||||||
Elf_Internal_Shdr *symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
|
the optimizations done on the second pass. */
|
||||||
|
for (pass = 0; pass < 2; ++pass)
|
||||||
|
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
|
||||||
|
{
|
||||||
|
Elf_Internal_Sym *locsyms = NULL;
|
||||||
|
Elf_Internal_Shdr *symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
|
||||||
|
|
||||||
for (sec = ibfd->sections; sec != NULL; sec = 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;
|
|
||||||
|
|
||||||
/* 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,
|
||||||
info->keep_memory);
|
info->keep_memory);
|
||||||
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++)
|
{
|
||||||
{
|
enum elf_ppc_reloc_type r_type;
|
||||||
enum elf_ppc_reloc_type r_type;
|
unsigned long r_symndx;
|
||||||
unsigned long r_symndx;
|
struct elf_link_hash_entry *h = NULL;
|
||||||
struct elf_link_hash_entry *h = NULL;
|
char *tls_mask;
|
||||||
char *tls_mask;
|
char tls_set, tls_clear;
|
||||||
char tls_set, tls_clear;
|
bfd_boolean is_local;
|
||||||
bfd_boolean is_local;
|
int expecting_tls_get_addr;
|
||||||
|
bfd_signed_vma *got_count;
|
||||||
|
|
||||||
r_symndx = ELF32_R_SYM (rel->r_info);
|
r_symndx = ELF32_R_SYM (rel->r_info);
|
||||||
if (r_symndx >= symtab_hdr->sh_info)
|
if (r_symndx >= symtab_hdr->sh_info)
|
||||||
{
|
{
|
||||||
struct elf_link_hash_entry **sym_hashes;
|
struct elf_link_hash_entry **sym_hashes;
|
||||||
|
|
||||||
sym_hashes = elf_sym_hashes (ibfd);
|
sym_hashes = elf_sym_hashes (ibfd);
|
||||||
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
|
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
|
||||||
while (h->root.type == bfd_link_hash_indirect
|
while (h->root.type == bfd_link_hash_indirect
|
||||||
|| h->root.type == bfd_link_hash_warning)
|
|| h->root.type == bfd_link_hash_warning)
|
||||||
h = (struct elf_link_hash_entry *) h->root.u.i.link;
|
h = (struct elf_link_hash_entry *) h->root.u.i.link;
|
||||||
}
|
}
|
||||||
|
|
||||||
is_local = FALSE;
|
expecting_tls_get_addr = 0;
|
||||||
if (h == NULL
|
is_local = FALSE;
|
||||||
|| !h->def_dynamic)
|
if (h == NULL
|
||||||
is_local = TRUE;
|
|| !h->def_dynamic)
|
||||||
|
is_local = TRUE;
|
||||||
|
|
||||||
r_type = ELF32_R_TYPE (rel->r_info);
|
r_type = ELF32_R_TYPE (rel->r_info);
|
||||||
switch (r_type)
|
switch (r_type)
|
||||||
{
|
{
|
||||||
case R_PPC_GOT_TLSLD16:
|
case R_PPC_GOT_TLSLD16:
|
||||||
case R_PPC_GOT_TLSLD16_LO:
|
case R_PPC_GOT_TLSLD16_LO:
|
||||||
case R_PPC_GOT_TLSLD16_HI:
|
expecting_tls_get_addr = 1;
|
||||||
case R_PPC_GOT_TLSLD16_HA:
|
/* Fall thru */
|
||||||
/* These relocs should never be against a symbol
|
|
||||||
defined in a shared lib. Leave them alone if
|
|
||||||
that turns out to be the case. */
|
|
||||||
expecting_tls_get_addr = 0;
|
|
||||||
htab->tlsld_got.refcount -= 1;
|
|
||||||
if (!is_local)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* LD -> LE */
|
case R_PPC_GOT_TLSLD16_HI:
|
||||||
tls_set = 0;
|
case R_PPC_GOT_TLSLD16_HA:
|
||||||
tls_clear = TLS_LD;
|
/* These relocs should never be against a symbol
|
||||||
expecting_tls_get_addr = 1;
|
defined in a shared lib. Leave them alone if
|
||||||
break;
|
that turns out to be the case. */
|
||||||
|
if (!is_local)
|
||||||
|
continue;
|
||||||
|
|
||||||
case R_PPC_GOT_TLSGD16:
|
/* LD -> LE */
|
||||||
case R_PPC_GOT_TLSGD16_LO:
|
|
||||||
case R_PPC_GOT_TLSGD16_HI:
|
|
||||||
case R_PPC_GOT_TLSGD16_HA:
|
|
||||||
if (is_local)
|
|
||||||
/* GD -> LE */
|
|
||||||
tls_set = 0;
|
tls_set = 0;
|
||||||
else
|
tls_clear = TLS_LD;
|
||||||
/* GD -> IE */
|
break;
|
||||||
tls_set = TLS_TLS | TLS_TPRELGD;
|
|
||||||
tls_clear = TLS_GD;
|
|
||||||
expecting_tls_get_addr = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case R_PPC_GOT_TPREL16:
|
case R_PPC_GOT_TLSGD16:
|
||||||
case R_PPC_GOT_TPREL16_LO:
|
case R_PPC_GOT_TLSGD16_LO:
|
||||||
case R_PPC_GOT_TPREL16_HI:
|
expecting_tls_get_addr = 1;
|
||||||
case R_PPC_GOT_TPREL16_HA:
|
/* Fall thru */
|
||||||
expecting_tls_get_addr = 0;
|
|
||||||
if (is_local)
|
case R_PPC_GOT_TLSGD16_HI:
|
||||||
{
|
case R_PPC_GOT_TLSGD16_HA:
|
||||||
/* IE -> LE */
|
if (is_local)
|
||||||
|
/* GD -> LE */
|
||||||
tls_set = 0;
|
tls_set = 0;
|
||||||
tls_clear = TLS_TPREL;
|
else
|
||||||
break;
|
/* GD -> IE */
|
||||||
}
|
tls_set = TLS_TLS | TLS_TPRELGD;
|
||||||
else
|
tls_clear = TLS_GD;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case R_PPC_GOT_TPREL16:
|
||||||
|
case R_PPC_GOT_TPREL16_LO:
|
||||||
|
case R_PPC_GOT_TPREL16_HI:
|
||||||
|
case R_PPC_GOT_TPREL16_HA:
|
||||||
|
if (is_local)
|
||||||
|
{
|
||||||
|
/* IE -> LE */
|
||||||
|
tls_set = 0;
|
||||||
|
tls_clear = TLS_TPREL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
default:
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
case R_PPC_REL14:
|
if (pass == 0)
|
||||||
case R_PPC_REL14_BRTAKEN:
|
{
|
||||||
case R_PPC_REL14_BRNTAKEN:
|
if (!expecting_tls_get_addr
|
||||||
case R_PPC_REL24:
|
|| !sec->has_tls_get_addr_call)
|
||||||
if (expecting_tls_get_addr
|
continue;
|
||||||
&& h != NULL
|
|
||||||
&& h == htab->tls_get_addr)
|
|
||||||
{
|
|
||||||
struct plt_entry *ent = find_plt_ent (h, NULL, 0);
|
|
||||||
if (ent != NULL && ent->plt.refcount > 0)
|
|
||||||
ent->plt.refcount -= 1;
|
|
||||||
}
|
|
||||||
expecting_tls_get_addr = 0;
|
|
||||||
continue;
|
|
||||||
|
|
||||||
default:
|
if (rel + 1 < relend
|
||||||
expecting_tls_get_addr = 0;
|
&& branch_reloc_hash_match (ibfd, rel + 1,
|
||||||
continue;
|
htab->tls_get_addr))
|
||||||
}
|
continue;
|
||||||
|
|
||||||
if (h != NULL)
|
/* Uh oh, we didn't find the expected call. We
|
||||||
{
|
could just mark this symbol to exclude it
|
||||||
if (tls_set == 0)
|
from tls optimization but it's safer to skip
|
||||||
{
|
the entire section. */
|
||||||
/* We managed to get rid of a got entry. */
|
sec->has_tls_reloc = 0;
|
||||||
if (h->got.refcount > 0)
|
break;
|
||||||
h->got.refcount -= 1;
|
}
|
||||||
}
|
|
||||||
tls_mask = &ppc_elf_hash_entry (h)->tls_mask;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Elf_Internal_Sym *sym;
|
|
||||||
bfd_signed_vma *lgot_refs;
|
|
||||||
char *lgot_masks;
|
|
||||||
|
|
||||||
if (locsyms == NULL)
|
if (h != NULL)
|
||||||
{
|
{
|
||||||
locsyms = (Elf_Internal_Sym *) symtab_hdr->contents;
|
tls_mask = &ppc_elf_hash_entry (h)->tls_mask;
|
||||||
if (locsyms == NULL)
|
got_count = &h->got.refcount;
|
||||||
locsyms = bfd_elf_get_elf_syms (ibfd, symtab_hdr,
|
}
|
||||||
symtab_hdr->sh_info,
|
else
|
||||||
0, NULL, NULL, NULL);
|
{
|
||||||
if (locsyms == NULL)
|
Elf_Internal_Sym *sym;
|
||||||
{
|
bfd_signed_vma *lgot_refs;
|
||||||
if (elf_section_data (sec)->relocs != relstart)
|
char *lgot_masks;
|
||||||
free (relstart);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sym = locsyms + r_symndx;
|
|
||||||
lgot_refs = elf_local_got_refcounts (ibfd);
|
|
||||||
if (lgot_refs == NULL)
|
|
||||||
abort ();
|
|
||||||
if (tls_set == 0)
|
|
||||||
{
|
|
||||||
/* We managed to get rid of a got entry. */
|
|
||||||
if (lgot_refs[r_symndx] > 0)
|
|
||||||
lgot_refs[r_symndx] -= 1;
|
|
||||||
}
|
|
||||||
lgot_masks = (char *) (lgot_refs + symtab_hdr->sh_info);
|
|
||||||
tls_mask = &lgot_masks[r_symndx];
|
|
||||||
}
|
|
||||||
|
|
||||||
*tls_mask |= tls_set;
|
if (locsyms == NULL)
|
||||||
*tls_mask &= ~tls_clear;
|
{
|
||||||
}
|
locsyms = (Elf_Internal_Sym *) symtab_hdr->contents;
|
||||||
|
if (locsyms == NULL)
|
||||||
|
locsyms = bfd_elf_get_elf_syms (ibfd, symtab_hdr,
|
||||||
|
symtab_hdr->sh_info,
|
||||||
|
0, NULL, NULL, NULL);
|
||||||
|
if (locsyms == NULL)
|
||||||
|
{
|
||||||
|
if (elf_section_data (sec)->relocs != relstart)
|
||||||
|
free (relstart);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sym = locsyms + r_symndx;
|
||||||
|
lgot_refs = elf_local_got_refcounts (ibfd);
|
||||||
|
if (lgot_refs == NULL)
|
||||||
|
abort ();
|
||||||
|
lgot_masks = (char *) (lgot_refs + symtab_hdr->sh_info);
|
||||||
|
tls_mask = &lgot_masks[r_symndx];
|
||||||
|
got_count = &lgot_refs[r_symndx];
|
||||||
|
}
|
||||||
|
|
||||||
if (elf_section_data (sec)->relocs != relstart)
|
if (tls_set == 0)
|
||||||
free (relstart);
|
{
|
||||||
|
/* We managed to get rid of a got entry. */
|
||||||
|
if (*got_count > 0)
|
||||||
|
*got_count -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expecting_tls_get_addr)
|
||||||
|
{
|
||||||
|
struct plt_entry *ent;
|
||||||
|
|
||||||
|
ent = find_plt_ent (htab->tls_get_addr, NULL, 0);
|
||||||
|
if (ent != NULL && ent->plt.refcount > 0)
|
||||||
|
ent->plt.refcount -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*tls_mask |= tls_set;
|
||||||
|
*tls_mask &= ~tls_clear;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elf_section_data (sec)->relocs != relstart)
|
||||||
|
free (relstart);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (locsyms != NULL
|
||||||
|
&& (symtab_hdr->contents != (unsigned char *) locsyms))
|
||||||
|
{
|
||||||
|
if (!info->keep_memory)
|
||||||
|
free (locsyms);
|
||||||
|
else
|
||||||
|
symtab_hdr->contents = (unsigned char *) locsyms;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (locsyms != NULL
|
|
||||||
&& (symtab_hdr->contents != (unsigned char *) locsyms))
|
|
||||||
{
|
|
||||||
if (!info->keep_memory)
|
|
||||||
free (locsyms);
|
|
||||||
else
|
|
||||||
symtab_hdr->contents = (unsigned char *) locsyms;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4615,8 +4748,11 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
|||||||
|
|
||||||
if (eh->tls_mask == (TLS_TLS | TLS_LD)
|
if (eh->tls_mask == (TLS_TLS | TLS_LD)
|
||||||
&& !eh->elf.def_dynamic)
|
&& !eh->elf.def_dynamic)
|
||||||
/* If just an LD reloc, we'll just use htab->tlsld_got.offset. */
|
{
|
||||||
eh->elf.got.offset = (bfd_vma) -1;
|
/* If just an LD reloc, we'll just use htab->tlsld_got.offset. */
|
||||||
|
htab->tlsld_got.refcount += 1;
|
||||||
|
eh->elf.got.offset = (bfd_vma) -1;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bfd_boolean dyn;
|
bfd_boolean dyn;
|
||||||
@ -4664,7 +4800,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
|||||||
if (info->shared)
|
if (info->shared)
|
||||||
{
|
{
|
||||||
/* Relocs that use pc_count are those that appear on a call insn,
|
/* Relocs that use pc_count are those that appear on a call insn,
|
||||||
or certain REL relocs (see MUST_BE_DYN_RELOC) that can be
|
or certain REL relocs (see must_be_dyn_reloc) that can be
|
||||||
generated via assembly. We want calls to protected symbols to
|
generated via assembly. We want calls to protected symbols to
|
||||||
resolve directly to the function rather than going via the plt.
|
resolve directly to the function rather than going via the plt.
|
||||||
If people want function pointer comparisons to work as expected
|
If people want function pointer comparisons to work as expected
|
||||||
@ -4891,6 +5027,9 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|
|||||||
*local_got = (bfd_vma) -1;
|
*local_got = (bfd_vma) -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Allocate space for global sym dynamic relocs. */
|
||||||
|
elf_link_hash_traverse (elf_hash_table (info), allocate_dynrelocs, info);
|
||||||
|
|
||||||
if (htab->tlsld_got.refcount > 0)
|
if (htab->tlsld_got.refcount > 0)
|
||||||
{
|
{
|
||||||
htab->tlsld_got.offset = allocate_got (htab, 8);
|
htab->tlsld_got.offset = allocate_got (htab, 8);
|
||||||
@ -4900,9 +5039,6 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|
|||||||
else
|
else
|
||||||
htab->tlsld_got.offset = (bfd_vma) -1;
|
htab->tlsld_got.offset = (bfd_vma) -1;
|
||||||
|
|
||||||
/* Allocate space for global sym dynamic relocs. */
|
|
||||||
elf_link_hash_traverse (elf_hash_table (info), allocate_dynrelocs, info);
|
|
||||||
|
|
||||||
if (htab->got != NULL && htab->plt_type != PLT_VXWORKS)
|
if (htab->got != NULL && htab->plt_type != PLT_VXWORKS)
|
||||||
{
|
{
|
||||||
unsigned int g_o_t = 32768;
|
unsigned int g_o_t = 32768;
|
||||||
@ -5754,16 +5890,13 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||||||
for the final instruction stream. */
|
for the final instruction stream. */
|
||||||
tls_mask = 0;
|
tls_mask = 0;
|
||||||
tls_gd = 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)
|
char *lgot_masks;
|
||||||
tls_mask = ((struct ppc_elf_link_hash_entry *) h)->tls_mask;
|
lgot_masks = (char *) (local_got_offsets + symtab_hdr->sh_info);
|
||||||
else if (local_got_offsets != NULL)
|
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. */
|
/* Ensure reloc mapping code below stays sane. */
|
||||||
@ -5870,85 +6003,147 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||||||
case R_PPC_GOT_TLSGD16_LO:
|
case R_PPC_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_PPC_GOT_TLSLD16:
|
case R_PPC_GOT_TLSLD16:
|
||||||
case R_PPC_GOT_TLSLD16_LO:
|
case R_PPC_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:
|
unsigned int insn1, insn2;
|
||||||
if (rel + 1 < relend)
|
bfd_vma offset;
|
||||||
|
|
||||||
|
tls_ldgd_opt:
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
enum elf_ppc_reloc_type r_type2;
|
/* IE */
|
||||||
unsigned long r_symndx2;
|
|
||||||
struct elf_link_hash_entry *h2;
|
|
||||||
bfd_vma insn1, insn2;
|
|
||||||
bfd_vma offset;
|
|
||||||
|
|
||||||
/* The next instruction should be a call to
|
|
||||||
__tls_get_addr. Peek at the reloc to be sure. */
|
|
||||||
r_type2 = ELF32_R_TYPE (rel[1].r_info);
|
|
||||||
r_symndx2 = ELF32_R_SYM (rel[1].r_info);
|
|
||||||
if (r_symndx2 < symtab_hdr->sh_info
|
|
||||||
|| (r_type2 != R_PPC_REL14
|
|
||||||
&& r_type2 != R_PPC_REL14_BRTAKEN
|
|
||||||
&& r_type2 != R_PPC_REL14_BRNTAKEN
|
|
||||||
&& r_type2 != R_PPC_REL24
|
|
||||||
&& r_type2 != R_PPC_PLTREL24))
|
|
||||||
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)
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* OK, it checks out. Replace the call. */
|
|
||||||
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);
|
||||||
if ((tls_mask & tls_gd) != 0)
|
insn1 &= (1 << 26) - 1;
|
||||||
|
insn1 |= 32 << 26; /* lwz */
|
||||||
|
if (offset != (bfd_vma) -1)
|
||||||
{
|
{
|
||||||
/* IE */
|
rel[1].r_info
|
||||||
insn1 &= (1 << 26) - 1;
|
= ELF32_R_INFO (ELF32_R_SYM (rel[1].r_info),
|
||||||
insn1 |= 32 << 26; /* lwz */
|
R_PPC_NONE);
|
||||||
insn2 = 0x7c631214; /* add 3,3,2 */
|
insn2 = 0x7c631214; /* add 3,3,2 */
|
||||||
rel[1].r_info = ELF32_R_INFO (r_symndx2, R_PPC_NONE);
|
bfd_put_32 (output_bfd, insn2, contents + offset);
|
||||||
rel[1].r_addend = 0;
|
|
||||||
r_type = (((r_type - (R_PPC_GOT_TLSGD16 & 3)) & 3)
|
|
||||||
+ R_PPC_GOT_TPREL16);
|
|
||||||
rel->r_info = ELF32_R_INFO (r_symndx, r_type);
|
|
||||||
}
|
}
|
||||||
else
|
r_type = (((r_type - (R_PPC_GOT_TLSGD16 & 3)) & 3)
|
||||||
{
|
+ R_PPC_GOT_TPREL16);
|
||||||
/* LE */
|
rel->r_info = ELF32_R_INFO (r_symndx, r_type);
|
||||||
insn1 = 0x3c620000; /* addis 3,2,0 */
|
}
|
||||||
insn2 = 0x38630000; /* addi 3,3,0 */
|
else
|
||||||
if (tls_gd == 0)
|
{
|
||||||
{
|
/* LE */
|
||||||
/* Was an LD reloc. */
|
insn1 = 0x3c620000; /* addis 3,2,0 */
|
||||||
r_symndx = 0;
|
|
||||||
rel->r_addend = htab->elf.tls_sec->vma + DTP_OFFSET;
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
bfd_put_32 (output_bfd, insn1, contents + rel->r_offset - d_offset);
|
|
||||||
bfd_put_32 (output_bfd, insn2, contents + offset);
|
|
||||||
if (tls_gd == 0)
|
if (tls_gd == 0)
|
||||||
{
|
{
|
||||||
/* We changed the symbol on an LD reloc. Start over
|
/* Was an LD reloc. */
|
||||||
in order to get h, sym, sec etc. right. */
|
for (r_symndx = 0;
|
||||||
rel--;
|
r_symndx < symtab_hdr->sh_info;
|
||||||
continue;
|
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_PPC_TPREL16_HA;
|
||||||
|
rel->r_info = ELF32_R_INFO (r_symndx, r_type);
|
||||||
|
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);
|
||||||
|
if (tls_gd == 0)
|
||||||
|
{
|
||||||
|
/* We changed the symbol on an LD reloc. Start over
|
||||||
|
in order to get h, sym, sec etc. right. */
|
||||||
|
rel--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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;
|
break;
|
||||||
}
|
}
|
||||||
@ -6003,6 +6198,8 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||||||
|
|
||||||
case R_PPC_NONE:
|
case R_PPC_NONE:
|
||||||
case R_PPC_TLS:
|
case R_PPC_TLS:
|
||||||
|
case R_PPC_TLSGD:
|
||||||
|
case R_PPC_TLSLD:
|
||||||
case R_PPC_EMB_MRKREF:
|
case R_PPC_EMB_MRKREF:
|
||||||
case R_PPC_GNU_VTINHERIT:
|
case R_PPC_GNU_VTINHERIT:
|
||||||
case R_PPC_GNU_VTENTRY:
|
case R_PPC_GNU_VTENTRY:
|
||||||
@ -6044,6 +6241,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||||||
case R_PPC_GOT16_LO:
|
case R_PPC_GOT16_LO:
|
||||||
case R_PPC_GOT16_HI:
|
case R_PPC_GOT16_HI:
|
||||||
case R_PPC_GOT16_HA:
|
case R_PPC_GOT16_HA:
|
||||||
|
tls_mask = 0;
|
||||||
dogot:
|
dogot:
|
||||||
{
|
{
|
||||||
/* Relocation is to the entry for this symbol in the global
|
/* Relocation is to the entry for this symbol in the global
|
||||||
@ -6342,7 +6540,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||||||
&& (h == NULL
|
&& (h == NULL
|
||||||
|| ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
|
|| ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
|
||||||
|| h->root.type != bfd_link_hash_undefweak)
|
|| h->root.type != bfd_link_hash_undefweak)
|
||||||
&& (MUST_BE_DYN_RELOC (r_type)
|
&& (must_be_dyn_reloc (info, r_type)
|
||||||
|| !SYMBOL_CALLS_LOCAL (info, h)))
|
|| !SYMBOL_CALLS_LOCAL (info, h)))
|
||||||
|| (ELIMINATE_COPY_RELOCS
|
|| (ELIMINATE_COPY_RELOCS
|
||||||
&& !info->shared
|
&& !info->shared
|
||||||
@ -6411,10 +6609,10 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||||||
outrel.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE);
|
outrel.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
long indx;
|
long indx = 0;
|
||||||
|
|
||||||
if (bfd_is_abs_section (sec))
|
if (r_symndx == 0 || bfd_is_abs_section (sec))
|
||||||
indx = 0;
|
;
|
||||||
else if (sec == NULL || sec->owner == NULL)
|
else if (sec == NULL || sec->owner == NULL)
|
||||||
{
|
{
|
||||||
bfd_set_error (bfd_error_bad_value);
|
bfd_set_error (bfd_error_bad_value);
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1169,6 +1169,8 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
|
|||||||
"BFD_RELOC_PPC64_PLTGOT16_DS",
|
"BFD_RELOC_PPC64_PLTGOT16_DS",
|
||||||
"BFD_RELOC_PPC64_PLTGOT16_LO_DS",
|
"BFD_RELOC_PPC64_PLTGOT16_LO_DS",
|
||||||
"BFD_RELOC_PPC_TLS",
|
"BFD_RELOC_PPC_TLS",
|
||||||
|
"BFD_RELOC_PPC_TLSGD",
|
||||||
|
"BFD_RELOC_PPC_TLSLD",
|
||||||
"BFD_RELOC_PPC_DTPMOD",
|
"BFD_RELOC_PPC_DTPMOD",
|
||||||
"BFD_RELOC_PPC_TPREL16",
|
"BFD_RELOC_PPC_TPREL16",
|
||||||
"BFD_RELOC_PPC_TPREL16_LO",
|
"BFD_RELOC_PPC_TPREL16_LO",
|
||||||
|
@ -2626,6 +2626,10 @@ ENUMDOC
|
|||||||
|
|
||||||
ENUM
|
ENUM
|
||||||
BFD_RELOC_PPC_TLS
|
BFD_RELOC_PPC_TLS
|
||||||
|
ENUMX
|
||||||
|
BFD_RELOC_PPC_TLSGD
|
||||||
|
ENUMX
|
||||||
|
BFD_RELOC_PPC_TLSLD
|
||||||
ENUMX
|
ENUMX
|
||||||
BFD_RELOC_PPC_DTPMOD
|
BFD_RELOC_PPC_DTPMOD
|
||||||
ENUMX
|
ENUMX
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* Object file "section" support for the BFD library.
|
/* Object file "section" support for the BFD library.
|
||||||
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
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.
|
Free Software Foundation, Inc.
|
||||||
Written by Cygnus Support.
|
Written by Cygnus Support.
|
||||||
|
|
||||||
@ -382,6 +382,9 @@ CODE_FRAGMENT
|
|||||||
. {* Nonzero if this section has TLS related relocations. *}
|
. {* Nonzero if this section has TLS related relocations. *}
|
||||||
. unsigned int has_tls_reloc:1;
|
. 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. *}
|
. {* Nonzero if this section has a gp reloc. *}
|
||||||
. unsigned int has_gp_reloc:1;
|
. unsigned int has_gp_reloc:1;
|
||||||
.
|
.
|
||||||
@ -642,11 +645,11 @@ CODE_FRAGMENT
|
|||||||
. {* segment_mark, sec_info_type, use_rela_p, has_tls_reloc, *} \
|
. {* segment_mark, sec_info_type, use_rela_p, has_tls_reloc, *} \
|
||||||
. 0, 0, 0, 0, \
|
. 0, 0, 0, 0, \
|
||||||
. \
|
. \
|
||||||
. {* has_gp_reloc, need_finalize_relax, reloc_done, *} \
|
. {* has_tls_get_addr_call, has_gp_reloc, need_finalize_relax, *} \
|
||||||
. 0, 0, 0, \
|
. 0, 0, 0, \
|
||||||
. \
|
. \
|
||||||
. {* vma, lma, size, rawsize *} \
|
. {* reloc_done, vma, lma, size, rawsize *} \
|
||||||
. 0, 0, 0, 0, \
|
. 0, 0, 0, 0, 0, \
|
||||||
. \
|
. \
|
||||||
. {* output_offset, output_section, alignment_power, *} \
|
. {* output_offset, output_section, alignment_power, *} \
|
||||||
. 0, (struct bfd_section *) &SEC, 0, \
|
. 0, (struct bfd_section *) &SEC, 0, \
|
||||||
|
@ -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.
|
||||||
|
|
||||||
2007-06-29 Joseph Myers <joseph@codesourcery.com>
|
2007-06-29 Joseph Myers <joseph@codesourcery.com>
|
||||||
|
|
||||||
* ppc.h (Tag_GNU_Power_ABI_FP): Define.
|
* ppc.h (Tag_GNU_Power_ABI_FP): Define.
|
||||||
|
@ -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_LO, 92)
|
||||||
RELOC_NUMBER (R_PPC_GOT_DTPREL16_HI, 93)
|
RELOC_NUMBER (R_PPC_GOT_DTPREL16_HI, 93)
|
||||||
RELOC_NUMBER (R_PPC_GOT_DTPREL16_HA, 94)
|
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
|
/* The remaining relocs are from the Embedded ELF ABI, and are not
|
||||||
in the SVR4 ELF ABI. */
|
in the SVR4 ELF ABI. */
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* PPC64 ELF support for BFD.
|
/* 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.
|
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_HIGHERA, 104)
|
||||||
RELOC_NUMBER (R_PPC64_DTPREL16_HIGHEST, 105)
|
RELOC_NUMBER (R_PPC64_DTPREL16_HIGHEST, 105)
|
||||||
RELOC_NUMBER (R_PPC64_DTPREL16_HIGHESTA, 106)
|
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. */
|
/* These are GNU extensions to enable C++ vtable garbage collection. */
|
||||||
RELOC_NUMBER (R_PPC64_GNU_VTINHERIT, 253)
|
RELOC_NUMBER (R_PPC64_GNU_VTINHERIT, 253)
|
||||||
|
@ -1386,6 +1386,9 @@ typedef struct bfd_section
|
|||||||
/* Nonzero if this section has TLS related relocations. */
|
/* Nonzero if this section has TLS related relocations. */
|
||||||
unsigned int has_tls_reloc:1;
|
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. */
|
/* Nonzero if this section has a gp reloc. */
|
||||||
unsigned int has_gp_reloc:1;
|
unsigned int has_gp_reloc:1;
|
||||||
|
|
||||||
@ -1646,11 +1649,11 @@ extern asection bfd_ind_section;
|
|||||||
/* segment_mark, sec_info_type, use_rela_p, has_tls_reloc, */ \
|
/* segment_mark, sec_info_type, use_rela_p, has_tls_reloc, */ \
|
||||||
0, 0, 0, 0, \
|
0, 0, 0, 0, \
|
||||||
\
|
\
|
||||||
/* has_gp_reloc, need_finalize_relax, reloc_done, */ \
|
/* has_tls_get_addr_call, has_gp_reloc, need_finalize_relax, */ \
|
||||||
0, 0, 0, \
|
0, 0, 0, \
|
||||||
\
|
\
|
||||||
/* vma, lma, size, rawsize */ \
|
/* reloc_done, vma, lma, size, rawsize */ \
|
||||||
0, 0, 0, 0, \
|
0, 0, 0, 0, 0, \
|
||||||
\
|
\
|
||||||
/* output_offset, output_section, alignment_power, */ \
|
/* output_offset, output_section, alignment_power, */ \
|
||||||
0, (struct bfd_section *) &SEC, 0, \
|
0, (struct bfd_section *) &SEC, 0, \
|
||||||
@ -2903,6 +2906,8 @@ in the instruction. */
|
|||||||
|
|
||||||
/* PowerPC and PowerPC64 thread-local storage relocations. */
|
/* PowerPC and PowerPC64 thread-local storage relocations. */
|
||||||
BFD_RELOC_PPC_TLS,
|
BFD_RELOC_PPC_TLS,
|
||||||
|
BFD_RELOC_PPC_TLSGD,
|
||||||
|
BFD_RELOC_PPC_TLSLD,
|
||||||
BFD_RELOC_PPC_DTPMOD,
|
BFD_RELOC_PPC_DTPMOD,
|
||||||
BFD_RELOC_PPC_TPREL16,
|
BFD_RELOC_PPC_TPREL16,
|
||||||
BFD_RELOC_PPC_TPREL16_LO,
|
BFD_RELOC_PPC_TPREL16_LO,
|
||||||
|
Loading…
Reference in New Issue
Block a user