summaryrefslogtreecommitdiffstats
path: root/bfd/elf64-ppc.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2010-01-25 06:47:16 +0000
committerAlan Modra <amodra@gmail.com>2010-01-25 06:47:16 +0000
commit766bc6567a42d77ac24103c5f7b9e14aaab81bba (patch)
tree6cb67fa0f34112fa7ee7a91847c496fdc9067e55 /bfd/elf64-ppc.c
parentd2c7a1a63b98c1add3d78ba71ffa9f2a105c1cd4 (diff)
downloadppe42-binutils-766bc6567a42d77ac24103c5f7b9e14aaab81bba.tar.gz
ppe42-binutils-766bc6567a42d77ac24103c5f7b9e14aaab81bba.zip
PR ld/11217
* elf64-ppc.c (ppc64_elf_tls_optimize): Optimize tls sequences with relocations against undefined weak symbols. (ppc64_elf_relocate_section): Don't optimize calls to undefined weak functions if the symbol is dynamic. (ppc64_elf_relocate_section): Edit tprel tls sequences. * elf32-ppc.c (ppc_elf_relocate_section): Likewise. (_bfd_elf_ppc_at_tprel_transform): New function. * bfd-in.h (_bfd_elf_ppc_at_tprel_transform): Declare. * bfd-in2.h: Regenerate.
Diffstat (limited to 'bfd/elf64-ppc.c')
-rw-r--r--bfd/elf64-ppc.c42
1 files changed, 34 insertions, 8 deletions
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index 6648ddca51..4a468812a5 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -7409,10 +7409,13 @@ ppc64_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
if (h != NULL)
{
- if (h->root.type != bfd_link_hash_defined
- && h->root.type != bfd_link_hash_defweak)
+ if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ value = h->root.u.def.value;
+ else if (h->root.type == bfd_link_hash_undefweak)
+ value = 0;
+ else
continue;
- value = h->root.u.def.value;
}
else
/* Symbols referenced by TLS relocs must be of type
@@ -7425,11 +7428,17 @@ ppc64_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
|| !h->def_dynamic)
{
is_local = TRUE;
- value += sym_sec->output_offset;
- value += sym_sec->output_section->vma;
- value -= htab->elf.tls_sec->vma;
- ok_tprel = (value + TP_OFFSET + ((bfd_vma) 1 << 31)
- < (bfd_vma) 1 << 32);
+ if (h != NULL
+ && h->root.type == bfd_link_hash_undefweak)
+ ok_tprel = TRUE;
+ else
+ {
+ value += sym_sec->output_offset;
+ value += sym_sec->output_section->vma;
+ value -= htab->elf.tls_sec->vma;
+ ok_tprel = (value + TP_OFFSET + ((bfd_vma) 1 << 31)
+ < (bfd_vma) 1 << 32);
+ }
}
r_type = ELF64_R_TYPE (rel->r_info);
@@ -11498,6 +11507,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
checking whether the function is defined. */
else if (h != NULL
&& h->elf.root.type == bfd_link_hash_undefweak
+ && h->elf.dynindx == -1
&& r_type == R_PPC64_REL24
&& relocation == 0
&& addend == 0)
@@ -11833,6 +11843,22 @@ ppc64_elf_relocate_section (bfd *output_bfd,
case R_PPC64_TPREL16_HIGHERA:
case R_PPC64_TPREL16_HIGHEST:
case R_PPC64_TPREL16_HIGHESTA:
+ if (h != NULL
+ && h->elf.root.type == bfd_link_hash_undefweak
+ && h->elf.dynindx == -1)
+ {
+ /* Make this relocation against an undefined weak symbol
+ resolve to zero. This is really just a tweak, since
+ code using weak externs ought to check that they are
+ defined before using them. */
+ bfd_byte *p = contents + rel->r_offset - d_offset;
+
+ insn = bfd_get_32 (output_bfd, p);
+ insn = _bfd_elf_ppc_at_tprel_transform (insn, 13);
+ if (insn != 0)
+ bfd_put_32 (output_bfd, insn, p);
+ break;
+ }
addend -= htab->elf.tls_sec->vma + TP_OFFSET;
if (info->shared)
/* The TPREL16 relocs shouldn't really be used in shared
OpenPOWER on IntegriCloud