aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf64-ppc.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2017-03-17 08:37:15 +1030
committerAlan Modra <amodra@gmail.com>2017-03-18 08:38:15 +1030
commit82e66161e649e5e801c40a52cba759292a76a59a (patch)
tree36a2ed05b7811ffcc8b4adcc8993433e18728fdd /bfd/elf64-ppc.c
parentd9cb6cdcfa12368f2f639f8cd06d18b94bd98a39 (diff)
downloadgdb-82e66161e649e5e801c40a52cba759292a76a59a.zip
gdb-82e66161e649e5e801c40a52cba759292a76a59a.tar.gz
gdb-82e66161e649e5e801c40a52cba759292a76a59a.tar.bz2
DT_TEXTREL vs IFUNC
If you should somehow link non-pic objects into a PIE or shared library, resulting in an object with DT_TEXTREL (text relocations) set, and your executable or shared library also contains GNU indirect functions, then you're in trouble. To apply dynamic relocations ld.so will make the text segment writable. On most systems this will make the text segment non-executable, which will then result in a segfault when ld.so tries to run ifunc resolvers when applying relocations against ifuncs. This patch teaches PowerPC ld to detect the situation, and warn. * 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.
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);