#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
if (!sec->used_by_bfd)
{
struct _ppc64_elf_section_data *sdata;
- bfd_size_type amt = sizeof (*sdata);
+ size_t amt = sizeof (*sdata);
sdata = bfd_zalloc (abfd, amt);
if (sdata == NULL)
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)
{
free_contents_and_exit_err:
count = -1;
free_contents_and_exit:
- if (contents)
- free (contents);
+ free (contents);
goto done;
}
ppc_stub_plt_branch:
Similar to the above, but a 24 bit branch in the stub section won't
reach its destination.
- . addis %r11,%r2,xxx@toc@ha
- . ld %r12,xxx@toc@l(%r11)
+ . addis %r12,%r2,xxx@toc@ha
+ . ld %r12,xxx@toc@l(%r12)
. mtctr %r12
. bctr
A ppc_stub_plt_branch with an r2 offset looks like:
. std %r2,40(%r1)
- . addis %r11,%r2,xxx@toc@ha
- . ld %r12,xxx@toc@l(%r11)
+ . addis %r12,%r2,xxx@toc@ha
+ . ld %r12,xxx@toc@l(%r12)
. addis %r2,%r2,off@ha
. addi %r2,%r2,off@l
. mtctr %r12
. mtctr %r12
. bctr
- There are also ELFv1 powerxx variants of these stubs.
+ There are also ELFv1 power10 variants of these stubs.
ppc_stub_long_branch_notoc:
. pla %r12,dest@pcrel
. b dest
In cases where the high instructions would add zero, they are
omitted and following instructions modified in some cases.
- For example, a powerxx ppc_stub_plt_call_notoc might simplify down
+ For example, a power10 ppc_stub_plt_call_notoc might simplify down
to
. pld %r12,xxx@pcrel
. mtctr %r12
struct ppc_link_hash_entry *next_dot_sym;
} u;
- /* Track dynamic relocs copied for this symbol. */
- struct elf_dyn_relocs *dyn_relocs;
-
/* Link between function code and descriptor symbols. */
struct ppc_link_hash_entry *oh;
/* Whether calls are made via the PLT from NOTOC functions. */
unsigned int notoc_plt:1;
- /* Whether to use powerxx instructions in linkage stubs. */
- unsigned int powerxx_stubs:1;
+ /* Whether to use power10 instructions in linkage stubs. */
+ unsigned int power10_stubs:1;
/* Incremented every time we size stubs. */
unsigned int stub_iteration;
ppc64_elf_link_hash_table_create (bfd *abfd)
{
struct ppc_link_hash_table *htab;
- bfd_size_type amt = sizeof (struct ppc_link_hash_table);
+ size_t amt = sizeof (struct ppc_link_hash_table);
htab = bfd_zmalloc (amt);
if (htab == NULL)
return;
/* Copy over any dynamic relocs we may have on the indirect sym. */
- if (eind->dyn_relocs != NULL)
+ if (ind->dyn_relocs != NULL)
{
- if (edir->dyn_relocs != NULL)
+ if (dir->dyn_relocs != NULL)
{
struct elf_dyn_relocs **pp;
struct elf_dyn_relocs *p;
/* Add reloc counts against the indirect sym to the direct sym
list. Merge any entries against the same section. */
- for (pp = &eind->dyn_relocs; (p = *pp) != NULL; )
+ for (pp = &ind->dyn_relocs; (p = *pp) != NULL; )
{
struct elf_dyn_relocs *q;
- for (q = edir->dyn_relocs; q != NULL; q = q->next)
+ for (q = dir->dyn_relocs; q != NULL; q = q->next)
if (q->sec == p->sec)
{
q->pc_count += p->pc_count;
if (q == NULL)
pp = &p->next;
}
- *pp = edir->dyn_relocs;
+ *pp = dir->dyn_relocs;
}
- edir->dyn_relocs = eind->dyn_relocs;
- eind->dyn_relocs = NULL;
+ dir->dyn_relocs = ind->dyn_relocs;
+ ind->dyn_relocs = NULL;
}
/* Copy over got entries that we may have already seen to the
break;
if (ent == NULL)
{
- bfd_size_type amt = sizeof (*ent);
+ size_t amt = sizeof (*ent);
ent = bfd_alloc (abfd, amt);
if (ent == NULL)
return FALSE;
break;
if (ent == NULL)
{
- bfd_size_type amt = sizeof (*ent);
+ size_t amt = sizeof (*ent);
ent = bfd_alloc (abfd, amt);
if (ent == NULL)
return FALSE;
case R_PPC64_PLT_PCREL34:
case R_PPC64_PLT_PCREL34_NOTOC:
case R_PPC64_PCREL28:
- htab->powerxx_stubs = 1;
+ htab->power10_stubs = 1;
break;
default:
break;
break;
if (ent == NULL)
{
- bfd_size_type amt = sizeof (*ent);
+ size_t amt = sizeof (*ent);
ent = bfd_alloc (abfd, amt);
if (ent == NULL)
return FALSE;
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:
struct elf_dyn_relocs *p;
struct elf_dyn_relocs **head;
- head = &ppc_elf_hash_entry (h)->dyn_relocs;
+ head = &h->dyn_relocs;
p = *head;
if (p == NULL || p->sec != sec)
{
return TRUE;
}
-/* Find dynamic relocs for H that apply to read-only sections. */
-
-static asection *
-readonly_dynrelocs (struct elf_link_hash_entry *h)
-{
- struct ppc_link_hash_entry *eh = ppc_elf_hash_entry (h);
- struct elf_dyn_relocs *p;
-
- for (p = eh->dyn_relocs; p != NULL; p = p->next)
- {
- asection *s = p->sec->output_section;
-
- if (s != NULL && (s->flags & SEC_READONLY) != 0)
- return p->sec;
- }
- return NULL;
-}
-
/* Return true if we have dynamic relocs against H or any of its weak
aliases, that apply to read-only sections. Cannot be used after
size_dynamic_sections. */
struct ppc_link_hash_entry *eh = ppc_elf_hash_entry (h);
do
{
- if (readonly_dynrelocs (&eh->elf))
+ if (_bfd_elf_readonly_dynrelocs (&eh->elf))
return TRUE;
eh = ppc_elf_hash_entry (eh->elf.u.alias);
}
{
struct elf_dyn_relocs *p;
- for (p = eh->dyn_relocs; p != NULL; p = p->next)
+ for (p = eh->elf.dyn_relocs; p != NULL; p = p->next)
if (p->pc_count != 0)
return TRUE;
return FALSE;
if (!bfd_link_pic (info)
&& h->type != STT_GNU_IFUNC
&& local)
- ppc_elf_hash_entry (h)->dyn_relocs = NULL;
+ h->dyn_relocs = NULL;
/* Clear procedure linkage table information for any symbol that
won't need a .plt entry. */
extra work in ld.so when resolving these symbols. */
if (global_entry_stub (h))
{
- if (!readonly_dynrelocs (h))
+ if (!_bfd_elf_readonly_dynrelocs (h))
{
h->pointer_equality_needed = 0;
/* If we haven't seen a branch reloc and the symbol
else if (!bfd_link_pic (info))
/* We are going to be defining the function symbol on the
plt stub, so no dyn_relocs needed when non-pic. */
- ppc_elf_hash_entry (h)->dyn_relocs = NULL;
+ h->dyn_relocs = NULL;
}
/* ELFv2 function symbols can't have copy relocs. */
return TRUE;
}
else if (!h->needs_plt
- && !readonly_dynrelocs (h))
+ && !_bfd_elf_readonly_dynrelocs (h))
{
/* If we haven't seen a branch reloc and the symbol isn't an
ifunc then we don't need a plt entry. */
h->root.u.def.value = def->root.u.def.value;
if (def->root.u.def.section == htab->elf.sdynbss
|| def->root.u.def.section == htab->elf.sdynrelro)
- ppc_elf_hash_entry (h)->dyn_relocs = NULL;
+ h->dyn_relocs = NULL;
return TRUE;
}
}
/* We no longer want dyn_relocs. */
- ppc_elf_hash_entry (h)->dyn_relocs = NULL;
+ h->dyn_relocs = NULL;
return _bfd_elf_adjust_dynamic_copy (info, h, s);
}
{
struct elf_dyn_relocs *p;
struct elf_dyn_relocs **pp;
- pp = &ppc_elf_hash_entry (h)->dyn_relocs;
+ pp = &h->dyn_relocs;
/* elf_gc_sweep may have already removed all dyn relocs associated
with local syms for a given section. Also, symbol flags are
bfd_byte *loc;
if (!bfd_malloc_and_get_section (ibfd, sec, &loc))
{
- if (loc != NULL)
- free (loc);
+ free (loc);
error_ret:
- if (local_syms != NULL
- && symtab_hdr->contents != (unsigned char *) local_syms)
+ if (symtab_hdr->contents != (unsigned char *) local_syms)
free (local_syms);
if (elf_section_data (sec)->relocs != relstart)
free (relstart);
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;
{
if (elf_section_data (sec)->relocs != relstart)
free (relstart);
- if (local_syms != NULL
- && symtab_hdr->contents != (bfd_byte *) local_syms)
+ if (symtab_hdr->contents != (bfd_byte *) local_syms)
free (local_syms);
return FALSE;
}
err_free_rel:
if (elf_section_data (sec)->relocs != relstart)
free (relstart);
- if (toc_ref != NULL)
- free (toc_ref);
- if (locsyms != NULL
- && (elf_symtab_hdr (ibfd).contents
- != (unsigned char *) locsyms))
+ free (toc_ref);
+ if (elf_symtab_hdr (ibfd).contents
+ != (unsigned char *) locsyms)
free (locsyms);
return ret;
}
}
}
- if (toc_ref != NULL)
- free (toc_ref);
+ free (toc_ref);
htab->do_tls_opt = 1;
return TRUE;
}
off = insn2 & 0xffff;
break;
+ case 6: /* lxvp, stxvp */
+ if ((insn2 & 0xe) != 0)
+ return FALSE;
+ insn1 = ((1ULL << 58) | (1ULL << 52)
+ | ((insn2 & 1) == 0 ? 58ULL << 26 : 62ULL << 26)
+ | (insn2 & (31ULL << 21)));
+ off = insn2 & 0xfff0;
+ break;
+
case 62: /* std, stq */
if ((insn2 & 1) != 0)
return FALSE;
if (used == NULL)
{
error_ret:
- if (local_syms != NULL
- && symtab_hdr->contents != (unsigned char *) local_syms)
+ if (symtab_hdr->contents != (unsigned char *) local_syms)
free (local_syms);
if (sec != NULL
- && relstart != NULL
&& elf_section_data (sec)->relocs != relstart)
free (relstart);
- if (toc_relocs != NULL
- && elf_section_data (toc)->relocs != toc_relocs)
+ if (elf_section_data (toc)->relocs != toc_relocs)
free (toc_relocs);
- if (skip != NULL)
- free (skip);
+ free (skip);
return FALSE;
}
rel_hdr->sh_size = toc->reloc_count * sz;
}
}
- else if (toc_relocs != NULL
- && elf_section_data (toc)->relocs != toc_relocs)
+ else if (elf_section_data (toc)->relocs != toc_relocs)
free (toc_relocs);
if (local_syms != NULL
if (relstart == NULL)
{
got_error_ret:
- if (local_syms != NULL
- && symtab_hdr->contents != (unsigned char *) local_syms)
+ if (symtab_hdr->contents != (unsigned char *) local_syms)
free (local_syms);
if (sec != NULL
- && relstart != NULL
&& elf_section_data (sec)->relocs != relstart)
free (relstart);
return FALSE;
|| 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;
IFUNCs which are handled even in static executables. */
if (!htab->elf.dynamic_sections_created
&& h->type != STT_GNU_IFUNC)
- eh->dyn_relocs = NULL;
+ h->dyn_relocs = NULL;
/* Discard relocs on undefined symbols that must be local. */
else if (h->root.type == bfd_link_hash_undefined
&& ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
- eh->dyn_relocs = NULL;
+ h->dyn_relocs = NULL;
/* Also discard relocs on undefined weak syms with non-default
visibility, or when dynamic_undefined_weak says so. */
else if (UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
- eh->dyn_relocs = NULL;
+ h->dyn_relocs = NULL;
- if (eh->dyn_relocs != NULL)
+ if (h->dyn_relocs != NULL)
{
struct elf_dyn_relocs *p, **pp;
avoid writing weird assembly. */
if (SYMBOL_CALLS_LOCAL (info, h))
{
- for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
+ for (pp = &h->dyn_relocs; (p = *pp) != NULL; )
{
p->count -= p->pc_count;
p->pc_count = 0;
}
}
- if (eh->dyn_relocs != NULL)
+ if (h->dyn_relocs != NULL)
{
/* Ensure we catch all the cases where this symbol
should be made dynamic. */
/* But if that didn't work out, discard dynamic relocs. */
if (h->dynindx == -1)
- eh->dyn_relocs = NULL;
+ h->dyn_relocs = NULL;
}
else
- eh->dyn_relocs = NULL;
+ h->dyn_relocs = NULL;
}
/* Finally, allocate space. */
- for (p = eh->dyn_relocs; p != NULL; p = p->next)
+ for (p = h->dyn_relocs; p != NULL; p = p->next)
{
asection *sreloc = elf_section_data (p->sec)->sreloc;
if (eh->elf.type == STT_GNU_IFUNC)
if (h->root.type == bfd_link_hash_indirect)
return TRUE;
- sec = readonly_dynrelocs (h);
+ sec = _bfd_elf_readonly_dynrelocs (h);
if (sec != NULL)
{
struct bfd_link_info *info = (struct bfd_link_info *) inf;
}
static bfd_byte *
-build_powerxx_offset (bfd *abfd, bfd_byte *p, bfd_vma off, int odd,
+build_power10_offset (bfd *abfd, bfd_byte *p, bfd_vma off, int odd,
bfd_boolean load)
{
uint64_t insn;
}
static unsigned int
-size_powerxx_offset (bfd_vma off, int odd)
+size_power10_offset (bfd_vma off, int odd)
{
if (off - odd + (1ULL << 33) < 1ULL << 34)
return odd + 8;
}
static unsigned int
-num_relocs_for_powerxx_offset (bfd_vma off, int odd)
+num_relocs_for_power10_offset (bfd_vma off, int odd)
{
if (off - odd + (1ULL << 33) < 1ULL << 34)
return 1;
}
static Elf_Internal_Rela *
-emit_relocs_for_powerxx_offset (struct bfd_link_info *info,
+emit_relocs_for_power10_offset (struct bfd_link_info *info,
Elf_Internal_Rela *r, bfd_vma roff,
bfd_vma targ, bfd_vma off, int odd)
{
if (stub_entry->stub_type >= ppc_stub_plt_call_notoc)
{
- if (htab->powerxx_stubs)
+ if (htab->power10_stubs)
{
bfd_vma start = (stub_entry->stub_offset
+ stub_entry->group->stub_sec->output_offset
+ stub_entry->group->stub_sec->output_section->vma);
if (stub_entry->stub_type > ppc_stub_plt_call_notoc)
start += 4;
- size = 8 + size_powerxx_offset (off, start & 4);
+ size = 8 + size_power10_offset (off, start & 4);
}
else
size = 8 + size_offset (off - 8);
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;
relp = p;
num_rel = 0;
- if (htab->powerxx_stubs)
+ if (htab->power10_stubs)
{
bfd_boolean load = stub_entry->stub_type >= ppc_stub_plt_call_notoc;
- p = build_powerxx_offset (htab->params->stub_bfd, p, off, odd, load);
+ p = build_power10_offset (htab->params->stub_bfd, p, off, odd, load);
}
else
{
if (info->emitrelocations)
{
bfd_vma roff = relp - stub_entry->group->stub_sec->contents;
- if (htab->powerxx_stubs)
- num_rel += num_relocs_for_powerxx_offset (off, odd);
+ if (htab->power10_stubs)
+ num_rel += num_relocs_for_power10_offset (off, odd);
else
{
num_rel += num_relocs_for_offset (off);
r = get_relocs (stub_entry->group->stub_sec, num_rel);
if (r == NULL)
return FALSE;
- if (htab->powerxx_stubs)
- r = emit_relocs_for_powerxx_offset (info, r, roff, targ, off, odd);
+ if (htab->power10_stubs)
+ r = emit_relocs_for_power10_offset (info, r, roff, targ, off, odd);
else
r = emit_relocs_for_offset (info, r, roff, targ, off);
if (stub_entry->stub_type == ppc_stub_long_branch_notoc
}
}
- if (!htab->powerxx_stubs
+ if (!htab->power10_stubs
&& htab->glink_eh_frame != NULL
&& htab->glink_eh_frame->size != 0)
{
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;
if (info->emitrelocations)
{
unsigned int num_rel;
- if (htab->powerxx_stubs)
- num_rel = num_relocs_for_powerxx_offset (off, odd);
+ if (htab->power10_stubs)
+ num_rel = num_relocs_for_power10_offset (off, odd);
else
num_rel = num_relocs_for_offset (off - 8);
stub_entry->group->stub_sec->reloc_count += num_rel;
stub_entry->group->stub_sec->flags |= SEC_RELOC;
}
- if (htab->powerxx_stubs)
- extra = size_powerxx_offset (off, odd);
+ if (htab->power10_stubs)
+ extra = size_power10_offset (off, odd);
else
extra = size_offset (off - 8);
/* Include branch insn plus those in the offset sequence. */
calculated. */
off -= extra;
- if (!htab->powerxx_stubs)
+ if (!htab->power10_stubs)
{
/* After the bcl, lr has been modified so we need to emit
.eh_frame info saying the return address is in r12. */
if (info->emitrelocations)
{
unsigned int num_rel;
- if (htab->powerxx_stubs)
- num_rel = num_relocs_for_powerxx_offset (off, odd);
+ if (htab->power10_stubs)
+ num_rel = num_relocs_for_power10_offset (off, odd);
else
num_rel = num_relocs_for_offset (off - 8);
stub_entry->group->stub_sec->reloc_count += num_rel;
size = plt_stub_size (htab, stub_entry, off);
- if (!htab->powerxx_stubs)
+ if (!htab->power10_stubs)
{
/* After the bcl, lr has been modified so we need to emit
.eh_frame info saying the return address is in r12. */
ppc64_elf_setup_section_lists (struct bfd_link_info *info)
{
unsigned int id;
- bfd_size_type amt;
+ size_t amt;
struct ppc_link_hash_table *htab = ppc_hash_table (info);
if (htab == NULL)
}
}
- if (local_syms != NULL
- && (elf_symtab_hdr (isec->owner).contents
- != (unsigned char *) local_syms))
+ if (elf_symtab_hdr (isec->owner).contents
+ != (unsigned char *) local_syms)
free (local_syms);
if (elf_section_data (isec)->relocs != relstart)
free (relstart);
if (elf_section_data (section)->relocs == NULL)
free (internal_relocs);
error_ret_free_local:
- if (local_syms != NULL
- && (symtab_hdr->contents
- != (unsigned char *) local_syms))
+ if (symtab_hdr->contents
+ != (unsigned char *) local_syms)
free (local_syms);
return FALSE;
}
}
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 (!get_sym_h (NULL, &sym, &sym_sec, NULL, &local_syms,
lplt - local_plt, ibfd))
{
- if (local_syms != NULL
- && symtab_hdr->contents != (unsigned char *) local_syms)
+ if (symtab_hdr->contents != (unsigned char *) local_syms)
free (local_syms);
return FALSE;
}
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);
if (bfd_link_pic (info)
? ((h == NULL
- || h->dyn_relocs != NULL)
+ || h->elf.dyn_relocs != NULL)
&& ((h != NULL && pc_dynrelocs (h))
|| must_be_dyn_reloc (info, r_type)))
: (h != NULL
- ? h->dyn_relocs != NULL
+ ? h->elf.dyn_relocs != NULL
: ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC))
{
bfd_boolean skip, relocate;
reloc_name, sym_name, (int) r);
ret = FALSE;
}
- if (more_info != NULL)
- free (more_info);
+ free (more_info);
}
copy_reloc:
if (wrel != rel)