diff options
author | Alan Modra <amodra@gmail.com> | 2022-06-27 18:17:18 +0930 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2022-06-28 13:02:26 +0930 |
commit | f40bb390bbf2c4a7a4ff0a042ac9ab9168ab6956 (patch) | |
tree | 37b9756be8a00ddfe472ed9ab64d48ad18a13749 /bfd/elf64-ppc.c | |
parent | 0f0d9373a3697ea2e464584dcea5cb7242b7208e (diff) | |
download | fsf-binutils-gdb-f40bb390bbf2c4a7a4ff0a042ac9ab9168ab6956.zip fsf-binutils-gdb-f40bb390bbf2c4a7a4ff0a042ac9ab9168ab6956.tar.gz fsf-binutils-gdb-f40bb390bbf2c4a7a4ff0a042ac9ab9168ab6956.tar.bz2 |
PowerPC64: align plt_branch stubs
plt_branch stubs are similar to plt_call stubs in that they branch
via bctr. Align them too.
bfd/
* elf64-ppc.c (ppc_size_one_stub): Align plt_branch stubs as for
plt_call stubs.
ld/
* testsuite/ld-powerpc/elfv2exe.d: Adjust for plt_branch changes.
* testsuite/ld-powerpc/notoc.d: Likewise.
* testsuite/ld-powerpc/notoc.wf: Likewise.
* testsuite/ld-powerpc/notoc3.d: Likewise.
* testsuite/ld-powerpc/pr23937.d: Likewise.
Diffstat (limited to 'bfd/elf64-ppc.c')
-rw-r--r-- | bfd/elf64-ppc.c | 54 |
1 files changed, 34 insertions, 20 deletions
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index 202c941..77e8f59 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -12393,6 +12393,8 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) if (PPC_LO (r2off) != 0) size += 4; } + pad = plt_stub_pad (htab->params->plt_stub_align, stub_offset, size); + stub_offset += pad; } else if (info->emitrelocations) { @@ -12415,6 +12417,38 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) odd = off & 4; off = targ - off; + if (stub_entry->type.sub == ppc_stub_notoc) + extra = size_power10_offset (off, odd); + else + extra = size_offset (off - 8); + /* Include branch insn plus those in the offset sequence. */ + size += 4 + extra; + + /* If the branch can't reach, use a plt_branch. + The branch insn is at the end, or "extra" bytes along. So + its offset will be "extra" bytes less that that already + calculated. */ + if (off - extra + (1 << 25) >= (bfd_vma) (1 << 26)) + { + stub_entry->type.main = ppc_stub_plt_branch; + size += 4; + pad = plt_stub_pad (htab->params->plt_stub_align, stub_offset, size); + if (pad != 0) + { + stub_offset += pad; + off -= pad; + odd ^= pad & 4; + size -= extra; + if (stub_entry->type.sub == ppc_stub_notoc) + extra = size_power10_offset (off, odd); + else + extra = size_offset (off - 8); + size += extra; + } + } + else if (info->emitrelocations) + stub_entry->group->stub_sec->reloc_count +=1; + if (info->emitrelocations) { unsigned int num_rel; @@ -12426,17 +12460,6 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) stub_entry->group->stub_sec->flags |= SEC_RELOC; } - if (stub_entry->type.sub == ppc_stub_notoc) - extra = size_power10_offset (off, odd); - else - extra = size_offset (off - 8); - /* Include branch insn plus those in the offset sequence. */ - size += 4 + extra; - /* The branch insn is at the end, or "extra" bytes along. So - its offset will be "extra" bytes less that that already - calculated. */ - off -= extra; - if (stub_entry->type.sub != ppc_stub_notoc) { /* After the bcl, lr has been modified so we need to emit @@ -12451,15 +12474,6 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) stub_entry->group->eh_size += eh_advance_size (delta) + 6; stub_entry->group->lr_restore = lr_used + 8; } - - /* If the branch can't reach, use a plt_branch. */ - if (off + (1 << 25) >= (bfd_vma) (1 << 26)) - { - stub_entry->type.main = ppc_stub_plt_branch; - size += 4; - } - else if (info->emitrelocations) - stub_entry->group->stub_sec->reloc_count +=1; } else if (stub_entry->type.sub >= ppc_stub_notoc) { |