From 888a7fc3665a67e20da1bce2f865b0ff9ef15842 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Mon, 22 Aug 2016 10:42:26 +0930 Subject: [PATCH] Error on unsupported PowerPC ifuncs The pr19784 tests fail on ppc32 due to a gcc bug. The failure should be noticed when building both libpr19784a.so and libpr19784b.so, rather than ld building a buggy libpr19784a.so that fails at run time. This patch fixes that by moving the @local ifunc check out of check_relocs, where a call destination may not yet be known to be ifunc. The patch also adds a related error for -mbss-plt code. * elf32-ppc.c (ppc_elf_check_relocs): Move error for @local ifunc.. (ppc_elf_relocate_section): ..to here. Comment. Error on detecting -mbss-plt -fPIC local ifuncs too. (ppc_elf_size_dynamic_sections): Comment on unnecessary glink branch table entries. --- bfd/ChangeLog | 8 ++++++++ bfd/elf32-ppc.c | 47 +++++++++++++++++++++++++++++++++++++---------- 2 files changed, 45 insertions(+), 10 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index ea810cdb66..b588fae779 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,11 @@ +2016-08-22 Alan Modra + + * elf32-ppc.c (ppc_elf_check_relocs): Move error for @local ifunc.. + (ppc_elf_relocate_section): ..to here. Comment. Error on + detecting -mbss-plt -fPIC local ifuncs too. + (ppc_elf_size_dynamic_sections): Comment on unnecessary glink + branch table entries. + 2016-08-19 Nick Clifton * elf.c (assign_section_numbers): Assign number for the .shstrtab diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index 8d5131a31e..92299bcc3d 100644 --- a/bfd/elf32-ppc.c +++ b/bfd/elf32-ppc.c @@ -4390,15 +4390,6 @@ ppc_elf_check_relocs (bfd *abfd, } if (h != NULL && h->type == STT_GNU_IFUNC) { - if (bfd_link_pic (info)) - { - info->callbacks->einfo - (_("%P: %H: @local call to ifunc %s\n"), - abfd, sec, rel->r_offset, - h->root.root.string); - bfd_set_error (bfd_error_bad_value); - return FALSE; - } h->needs_plt = 1; if (!update_plt_info (abfd, &h->plt.plist, NULL, 0)) return FALSE; @@ -6504,7 +6495,9 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd, && htab->elf.dynamic_sections_created) { htab->glink_pltresolve = htab->glink->size; - /* Space for the branch table. */ + /* Space for the branch table. ??? We don't need entries for + non-dynamic symbols in this table. This case can arise with + static ifuncs or forced local ifuncs. */ htab->glink->size += htab->glink->size / (GLINK_ENTRY_SIZE / 4) - 4; /* Pad out to align the start of PLTresolve. */ htab->glink->size += -htab->glink->size & (htab->params->ppc476_workaround @@ -8308,6 +8301,26 @@ ppc_elf_relocate_section (bfd *output_bfd, } if (ent != NULL) { + if (bfd_link_pic (info) + && ent->sec != got2 + && htab->plt_type != PLT_NEW + && (!htab->elf.dynamic_sections_created + || h == NULL + || h->dynindx == -1)) + { + /* Uh oh, we are going to create a pic glink stub + for an ifunc (here for h == NULL and later in + finish_dynamic_symbol for h != NULL), and + apparently are using code compiled with + -mbss-plt. The difficulty is that -mbss-plt code + gives no indication via a magic PLTREL24 addend + whether r30 is equal to _GLOBAL_OFFSET_TABLE_ or + is pointing into a .got2 section (and how far + into .got2). */ + info->callbacks->einfo + (_("%X%P: %H: unsupported bss-plt -fPIC ifunc %s\n"), + input_bfd, input_section, rel->r_offset, sym_name); + } if (h == NULL && (ent->plt.offset & 1) == 0) { Elf_Internal_Rela rela; @@ -8656,6 +8669,20 @@ ppc_elf_relocate_section (bfd *output_bfd, TRUE); goto copy_reloc; } + if (h != NULL && h->type == STT_GNU_IFUNC && bfd_link_pic (info)) + { + /* @local on an ifunc does not really make sense since + the ifunc resolver can take you anywhere. More + seriously, calls to ifuncs must go through a plt call + stub, and for pic the plt call stubs uses r30 to + access the PLT. The problem is that a call that is + local won't have the +32k reloc addend trick marking + -fPIC code, so the linker won't know whether r30 is + _GLOBAL_OFFSET_TABLE_ or pointing into a .got2 section. */ + info->callbacks->einfo (_("%X%P: %H: @local call to ifunc %s\n"), + input_bfd, input_section, rel->r_offset, + h->root.root.string); + } break; case R_PPC_DTPREL16: