diff options
-rw-r--r-- | bfd/ChangeLog | 18 | ||||
-rw-r--r-- | bfd/elf32-ppc.c | 69 | ||||
-rw-r--r-- | bfd/elf64-ppc.c | 44 |
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); |