summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2016-08-22 10:42:26 +0930
committerAlan Modra <amodra@gmail.com>2016-08-22 10:55:08 +0930
commit888a7fc3665a67e20da1bce2f865b0ff9ef15842 (patch)
treea77aa2665fc2ede6e874d4d424dc6d505c2a20c6
parentca942b53cec608a3df1a351b504852e4e64c5e90 (diff)
downloadbinutils-gdb-888a7fc3665a67e20da1bce2f865b0ff9ef15842.tar.gz
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.
-rw-r--r--bfd/ChangeLog8
-rw-r--r--bfd/elf32-ppc.c47
2 files changed, 45 insertions, 10 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index ea810cdb668..b588fae7793 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,11 @@
+2016-08-22 Alan Modra <amodra@gmail.com>
+
+ * 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 <nickc@redhat.com>
* elf.c (assign_section_numbers): Assign number for the .shstrtab
diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index 8d5131a31ef..92299bcc3dd 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: