aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf64-ppc.c
diff options
context:
space:
mode:
Diffstat (limited to 'bfd/elf64-ppc.c')
-rw-r--r--bfd/elf64-ppc.c44
1 files changed, 38 insertions, 6 deletions
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index c9a3f21..1193c1f 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -4105,6 +4105,11 @@ struct ppc_link_hash_table
/* Whether func_desc_adjust needs to be run over symbols. */
unsigned int need_func_desc_adj:1;
+ /* Whether there exist local gnu indirect function resolvers,
+ referenced by dynamic relocations. */
+ unsigned int local_ifunc_resolver:1;
+ unsigned int maybe_local_ifunc_resolver:1;
+
/* Incremented every time we size stubs. */
unsigned int stub_iteration;
@@ -11164,6 +11169,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
* sizeof (Elf64_External_Rela)));
bfd_elf64_swap_reloca_out (info->output_bfd, &rela, rl);
stub_entry->plt_ent->plt.offset |= 1;
+ htab->local_ifunc_resolver = 1;
}
off = (dest
@@ -14485,7 +14491,13 @@ ppc64_elf_relocate_section (bfd *output_bfd,
? h->elf.type == STT_GNU_IFUNC
: ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC);
if (ifunc)
- relgot = htab->elf.irelplt;
+ {
+ relgot = htab->elf.irelplt;
+ if (indx == 0)
+ htab->local_ifunc_resolver = 1;
+ else if (is_static_defined (&h->elf))
+ htab->maybe_local_ifunc_resolver = 1;
+ }
else if (indx != 0
|| (bfd_link_pic (info)
&& (h == NULL
@@ -14815,6 +14827,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
bfd_boolean skip, relocate;
asection *sreloc;
bfd_vma out_off;
+ long indx = 0;
/* When generating a dynamic object, these relocations
are copied into the output file to be resolved at run
@@ -14851,8 +14864,9 @@ ppc64_elf_relocate_section (bfd *output_bfd,
&& !is_opd
&& r_type != R_PPC64_TOC)
{
- BFD_ASSERT (h->elf.dynindx != -1);
- outrel.r_info = ELF64_R_INFO (h->elf.dynindx, r_type);
+ indx = h->elf.dynindx;
+ BFD_ASSERT (indx != -1);
+ outrel.r_info = ELF64_R_INFO (indx, r_type);
}
else
{
@@ -14895,8 +14909,6 @@ ppc64_elf_relocate_section (bfd *output_bfd,
}
else
{
- long indx = 0;
-
if (h != NULL
? h->elf.type == STT_GNU_IFUNC
: ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
@@ -14951,7 +14963,13 @@ ppc64_elf_relocate_section (bfd *output_bfd,
if (h != NULL
? h->elf.type == STT_GNU_IFUNC
: ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
- sreloc = htab->elf.irelplt;
+ {
+ sreloc = htab->elf.irelplt;
+ if (indx == 0)
+ htab->local_ifunc_resolver = 1;
+ else if (is_static_defined (&h->elf))
+ htab->maybe_local_ifunc_resolver = 1;
+ }
if (sreloc == NULL)
abort ();
@@ -15437,6 +15455,7 @@ ppc64_elf_finish_dynamic_symbol (bfd *output_bfd,
loc = (htab->elf.irelplt->contents
+ (htab->elf.irelplt->reloc_count++
* sizeof (Elf64_External_Rela)));
+ htab->local_ifunc_resolver = 1;
}
else
{
@@ -15448,6 +15467,8 @@ ppc64_elf_finish_dynamic_symbol (bfd *output_bfd,
loc = (htab->elf.srelplt->contents
+ ((ent->plt.offset - PLT_INITIAL_ENTRY_SIZE (htab))
/ PLT_ENTRY_SIZE (htab) * sizeof (Elf64_External_Rela)));
+ if (h->type == STT_GNU_IFUNC && is_static_defined (h))
+ htab->maybe_local_ifunc_resolver = 1;
}
bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
@@ -15613,6 +15634,17 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd,
case DT_PLTRELSZ:
dyn.d_un.d_val = htab->elf.srelplt->size;
break;
+
+ case DT_TEXTREL:
+ if (htab->local_ifunc_resolver)
+ info->callbacks->einfo
+ (_("%X%P: text relocations and GNU indirect "
+ "functions will result in a segfault at runtime\n"));
+ else if (htab->maybe_local_ifunc_resolver)
+ info->callbacks->einfo
+ (_("%P: warning: text relocations and GNU indirect "
+ "functions may result in a segfault at runtime\n"));
+ continue;
}
bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);