#define elf_backend_finish_dynamic_sections ppc64_elf_finish_dynamic_sections
#define elf_backend_link_output_symbol_hook ppc64_elf_output_symbol_hook
#define elf_backend_special_sections ppc64_elf_special_sections
+#define elf_backend_section_flags ppc64_elf_section_flags
#define elf_backend_merge_symbol_attribute ppc64_elf_merge_symbol_attribute
#define elf_backend_merge_symbol ppc64_elf_merge_symbol
#define elf_backend_get_reloc_section bfd_get_section_by_name
return _bfd_elf_new_section_hook (abfd, sec);
}
+static bfd_boolean
+ppc64_elf_section_flags (const Elf_Internal_Shdr *hdr)
+{
+ const char *name = hdr->bfd_section->name;
+
+ if (strncmp (name, ".sbss", 5) == 0
+ || strncmp (name, ".sdata", 6) == 0)
+ hdr->bfd_section->flags |= SEC_SMALL_DATA;
+
+ return TRUE;
+}
+
static struct _opd_sec_data *
get_opd_info (asection * sec)
{
if (!update_local_sym_info (abfd, symtab_hdr, r_symndx,
rel->r_addend, tls_type))
return FALSE;
-
- /* We may also need a plt entry if the symbol turns out to be
- an ifunc. */
- if (h != NULL && !bfd_link_pic (info) && abiversion (abfd) != 1)
- {
- if (!update_plt_info (abfd, &h->plt.plist, rel->r_addend))
- return FALSE;
- }
break;
case R_PPC64_PLT16_HA:
return FALSE;
relend = relstart + sec->reloc_count;
- for (rel = relstart; rel < relend; )
+ for (rel = relstart; rel < relend; rel++)
{
enum elf_ppc64_reloc_type r_type;
unsigned long r_symndx;
|| discarded_section (sym_sec))
continue;
+ if ((h ? h->type : ELF_ST_TYPE (sym->st_info)) == STT_GNU_IFUNC)
+ continue;
+
if (!SYMBOL_REFERENCES_LOCAL (info, h))
continue;
stub_entry = (struct ppc_stub_hash_entry *) gen_entry;
info = in_arg;
+ /* Fail if the target section could not be assigned to an output
+ section. The user should fix his linker script. */
+ if (stub_entry->target_section != NULL
+ && stub_entry->target_section->output_section == NULL
+ && info->non_contiguous_regions)
+ info->callbacks->einfo (_("%F%P: Could not assign '%pA' to an output section. "
+ "Retry without --enable-non-contiguous-regions.\n"),
+ stub_entry->target_section);
+
+ /* Same for the group. */
+ if (stub_entry->group->stub_sec != NULL
+ && stub_entry->group->stub_sec->output_section == NULL
+ && info->non_contiguous_regions)
+ info->callbacks->einfo (_("%F%P: Could not assign group %pA target %pA to an "
+ "output section. Retry without "
+ "--enable-non-contiguous-regions.\n"),
+ stub_entry->group->stub_sec,
+ stub_entry->target_section);
+
htab = ppc_hash_table (info);
if (htab == NULL)
return FALSE;
if (htab == NULL)
return FALSE;
+ /* Fail if the target section could not be assigned to an output
+ section. The user should fix his linker script. */
+ if (stub_entry->target_section != NULL
+ && stub_entry->target_section->output_section == NULL
+ && info->non_contiguous_regions)
+ info->callbacks->einfo (_("%F%P: Could not assign %pA to an output section. "
+ "Retry without --enable-non-contiguous-regions.\n"),
+ stub_entry->target_section);
+
+ /* Same for the group. */
+ if (stub_entry->group->stub_sec != NULL
+ && stub_entry->group->stub_sec->output_section == NULL
+ && info->non_contiguous_regions)
+ info->callbacks->einfo (_("%F%P: Could not assign group %pA target %pA to an "
+ "output section. Retry without "
+ "--enable-non-contiguous-regions.\n"),
+ stub_entry->group->stub_sec,
+ stub_entry->target_section);
+
/* Make a note of the offset within the stubs for this entry. */
stub_entry->stub_offset = stub_entry->group->stub_sec->size;
}
maybe_strip_output (info, htab->brlt);
+ if (htab->relbrlt != NULL)
+ maybe_strip_output (info, htab->relbrlt);
if (htab->glink_eh_frame != NULL)
maybe_strip_output (info, htab->glink_eh_frame);
if (stats != NULL)
{
- size_t len;
- *stats = bfd_malloc (500);
- if (*stats == NULL)
- return FALSE;
-
- len = sprintf (*stats,
- ngettext ("linker stubs in %u group\n",
- "linker stubs in %u groups\n",
- stub_sec_count),
- stub_sec_count);
- sprintf (*stats + len, _(" branch %lu\n"
- " branch toc adj %lu\n"
- " branch notoc %lu\n"
- " branch both %lu\n"
- " long branch %lu\n"
- " long toc adj %lu\n"
- " long notoc %lu\n"
- " long both %lu\n"
- " plt call %lu\n"
- " plt call save %lu\n"
- " plt call notoc %lu\n"
- " plt call both %lu\n"
- " global entry %lu"),
- htab->stub_count[ppc_stub_long_branch - 1],
- htab->stub_count[ppc_stub_long_branch_r2off - 1],
- htab->stub_count[ppc_stub_long_branch_notoc - 1],
- htab->stub_count[ppc_stub_long_branch_both - 1],
- htab->stub_count[ppc_stub_plt_branch - 1],
- htab->stub_count[ppc_stub_plt_branch_r2off - 1],
- htab->stub_count[ppc_stub_plt_branch_notoc - 1],
- htab->stub_count[ppc_stub_plt_branch_both - 1],
- htab->stub_count[ppc_stub_plt_call - 1],
- htab->stub_count[ppc_stub_plt_call_r2save - 1],
- htab->stub_count[ppc_stub_plt_call_notoc - 1],
- htab->stub_count[ppc_stub_plt_call_both - 1],
- htab->stub_count[ppc_stub_global_entry - 1]);
+ char *groupmsg;
+ if (asprintf (&groupmsg,
+ ngettext ("linker stubs in %u group\n",
+ "linker stubs in %u groups\n",
+ stub_sec_count),
+ stub_sec_count) < 0)
+ *stats = NULL;
+ else
+ {
+ if (asprintf (stats, _("%s"
+ " branch %lu\n"
+ " branch toc adj %lu\n"
+ " branch notoc %lu\n"
+ " branch both %lu\n"
+ " long branch %lu\n"
+ " long toc adj %lu\n"
+ " long notoc %lu\n"
+ " long both %lu\n"
+ " plt call %lu\n"
+ " plt call save %lu\n"
+ " plt call notoc %lu\n"
+ " plt call both %lu\n"
+ " global entry %lu"),
+ groupmsg,
+ htab->stub_count[ppc_stub_long_branch - 1],
+ htab->stub_count[ppc_stub_long_branch_r2off - 1],
+ htab->stub_count[ppc_stub_long_branch_notoc - 1],
+ htab->stub_count[ppc_stub_long_branch_both - 1],
+ htab->stub_count[ppc_stub_plt_branch - 1],
+ htab->stub_count[ppc_stub_plt_branch_r2off - 1],
+ htab->stub_count[ppc_stub_plt_branch_notoc - 1],
+ htab->stub_count[ppc_stub_plt_branch_both - 1],
+ htab->stub_count[ppc_stub_plt_call - 1],
+ htab->stub_count[ppc_stub_plt_call_r2save - 1],
+ htab->stub_count[ppc_stub_plt_call_notoc - 1],
+ htab->stub_count[ppc_stub_plt_call_both - 1],
+ htab->stub_count[ppc_stub_global_entry - 1]) < 0)
+ *stats = NULL;
+ free (groupmsg);
+ }
}
return TRUE;
}
break;
case R_PPC64_GOT16_DS:
+ if ((h ? h->elf.type : ELF_ST_TYPE (sym->st_info)) == STT_GNU_IFUNC)
+ break;
from = TOCstart + htab->sec_info[input_section->id].toc_off;
if (relocation + addend - from + 0x8000 < 0x10000
&& SYMBOL_REFERENCES_LOCAL (info, &h->elf))
case R_PPC64_GOT16_LO_DS:
case R_PPC64_GOT16_HA:
+ if ((h ? h->elf.type : ELF_ST_TYPE (sym->st_info)) == STT_GNU_IFUNC)
+ break;
from = TOCstart + htab->sec_info[input_section->id].toc_off;
if (relocation + addend - from + 0x80008000ULL < 0x100000000ULL
&& SYMBOL_REFERENCES_LOCAL (info, &h->elf))
break;
case R_PPC64_GOT_PCREL34:
+ if ((h ? h->elf.type : ELF_ST_TYPE (sym->st_info)) == STT_GNU_IFUNC)
+ break;
from = (rel->r_offset
+ input_section->output_section->vma
+ input_section->output_offset);