. 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
/* 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;
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;
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:
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;
|| 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;
}
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);
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 (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. */
}
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);
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);