aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog18
-rw-r--r--bfd/elf32-ppc.c69
-rw-r--r--bfd/elf64-ppc.c44
3 files changed, 109 insertions, 22 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 664285b..5dea352 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,21 @@
+2017-03-18 Alan Modra <amodra@gmail.com>
+
+ * elf64-ppc.c (struct ppc_link_hash_table): Add
+ local_ifunc_resolver and maybe_local_ifunc_resolver.
+ (ppc_build_one_stub): Set flags on emitting dynamic
+ relocation to ifunc.
+ (ppc64_elf_relocate_section): Likewise.
+ (ppc64_elf_finish_dynamic_symbol): Likewise.
+ (ppc64_elf_finish_dynamic_sections): Error on DT_TEXTREL with
+ local dynamic relocs to ifuncs.
+ * elf32-ppc.c (struct ppc_elf_link_hash_table): Add
+ local_ifunc_resolver and maybe_local_ifunc_resolver.
+ (ppc_elf_relocate_section): Set flag on emitting dynamic
+ relocation to ifuncs.
+ (ppc_elf_finish_dynamic_symbol): Likewise.
+ (ppc_elf_finish_dynamic_sections): Error on DT_TEXTREL with local
+ dynamic relocs to ifuncs.
+
2017-03-13 Nick Clifton <nickc@redhat.com>
PR binutils/21202
diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index 72ead48..4bd58e2 100644
--- a/bfd/elf32-ppc.c
+++ b/bfd/elf32-ppc.c
@@ -3327,6 +3327,11 @@ struct ppc_elf_link_hash_table
/* True if the target system is VxWorks. */
unsigned int is_vxworks: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;
+
/* The size of PLT entries. */
int plt_entry_size;
/* The distance between adjacent PLT slots. */
@@ -8386,6 +8391,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
loc += (htab->elf.irelplt->reloc_count++
* sizeof (Elf32_External_Rela));
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
+ htab->local_ifunc_resolver = 1;
ent->plt.offset |= 1;
}
@@ -8574,7 +8580,13 @@ ppc_elf_relocate_section (bfd *output_bfd,
bfd_byte * loc;
if (ifunc != NULL)
- rsec = htab->elf.irelplt;
+ {
+ rsec = htab->elf.irelplt;
+ if (indx == 0)
+ htab->local_ifunc_resolver = 1;
+ else if (is_static_defined (h))
+ htab->maybe_local_ifunc_resolver = 1;
+ }
outrel.r_offset = (htab->elf.sgot->output_section->vma
+ htab->elf.sgot->output_offset
+ off);
@@ -8867,6 +8879,8 @@ ppc_elf_relocate_section (bfd *output_bfd,
int skip;
bfd_byte *loc;
asection *sreloc;
+ long indx = 0;
+
#ifdef DEBUG
fprintf (stderr, "ppc_elf_relocate_section needs to "
"create relocation for %s\n",
@@ -8877,12 +8891,6 @@ ppc_elf_relocate_section (bfd *output_bfd,
/* When generating a shared object, these relocations
are copied into the output file to be resolved at run
time. */
- sreloc = elf_section_data (input_section)->sreloc;
- if (ifunc)
- sreloc = htab->elf.irelplt;
- if (sreloc == NULL)
- return FALSE;
-
skip = 0;
outrel.r_offset = _bfd_elf_section_offset (output_bfd, info,
input_section,
@@ -8900,9 +8908,10 @@ ppc_elf_relocate_section (bfd *output_bfd,
|| h->root.type == bfd_link_hash_undefweak))
|| !SYMBOL_REFERENCES_LOCAL (info, h))
{
- BFD_ASSERT (h->dynindx != -1);
+ indx = h->dynindx;
+ BFD_ASSERT (indx != -1);
unresolved_reloc = FALSE;
- outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
+ outrel.r_info = ELF32_R_INFO (indx, r_type);
outrel.r_addend = rel->r_addend;
}
else
@@ -8911,8 +8920,6 @@ ppc_elf_relocate_section (bfd *output_bfd,
if (r_type != R_PPC_ADDR32)
{
- long indx = 0;
-
if (ifunc != NULL)
{
/* If we get here when building a static
@@ -8977,6 +8984,18 @@ ppc_elf_relocate_section (bfd *output_bfd,
outrel.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE);
}
+ sreloc = elf_section_data (input_section)->sreloc;
+ if (ifunc)
+ {
+ sreloc = htab->elf.irelplt;
+ if (indx == 0)
+ htab->local_ifunc_resolver = 1;
+ else if (is_static_defined (h))
+ htab->maybe_local_ifunc_resolver = 1;
+ }
+ if (sreloc == NULL)
+ return FALSE;
+
loc = sreloc->contents;
loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rela);
bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
@@ -10267,12 +10286,19 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd,
if (!htab->elf.dynamic_sections_created
|| h->dynindx == -1)
- loc = (htab->elf.irelplt->contents
- + (htab->elf.irelplt->reloc_count++
- * sizeof (Elf32_External_Rela)));
+ {
+ loc = (htab->elf.irelplt->contents
+ + (htab->elf.irelplt->reloc_count++
+ * sizeof (Elf32_External_Rela)));
+ htab->local_ifunc_resolver = 1;
+ }
else
- loc = (htab->elf.srelplt->contents
- + reloc_index * sizeof (Elf32_External_Rela));
+ {
+ loc = (htab->elf.srelplt->contents
+ + reloc_index * sizeof (Elf32_External_Rela));
+ if (h->type == STT_GNU_IFUNC && is_static_defined (h))
+ htab->maybe_local_ifunc_resolver = 1;
+ }
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
if (!h->def_regular)
@@ -10477,6 +10503,17 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
dyn.d_un.d_ptr = got;
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;
+
default:
if (htab->is_vxworks
&& elf_vxworks_finish_dynamic_entry (output_bfd, &dyn))
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);