mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-01-30 12:44:10 +08:00
PowerPC relocations for prefix insns
include/ * elf/ppc64.h (R_PPC64_PLTSEQ_NOTOC, R_PPC64_PLTCALL_NOTOC), (R_PPC64_PCREL_OPT, R_PPC64_D34, R_PPC64_D34_LO, R_PPC64_D34_HI30), (R_PPC64_D34_HA30, R_PPC64_PCREL34, R_PPC64_GOT_PCREL34), (R_PPC64_PLT_PCREL34, R_PPC64_PLT_PCREL34_NOTOC), (R_PPC64_ADDR16_HIGHER34, R_PPC64_ADDR16_HIGHERA34), (R_PPC64_ADDR16_HIGHEST34, R_PPC64_ADDR16_HIGHESTA34), (R_PPC64_REL16_HIGHER34, R_PPC64_REL16_HIGHERA34), (R_PPC64_REL16_HIGHEST34, R_PPC64_REL16_HIGHESTA34), (R_PPC64_D28, R_PPC64_PCREL28): Define. bfd/ * reloc.c (BFD_RELOC_PPC64_D34, BFD_RELOC_PPC64_D34_LO), (BFD_RELOC_PPC64_D34_HI30, BFD_RELOC_PPC64_D34_HA30), (BFD_RELOC_PPC64_PCREL34, BFD_RELOC_PPC64_GOT_PCREL34), (BFD_RELOC_PPC64_PLT_PCREL34), (BFD_RELOC_PPC64_ADDR16_HIGHER34, BFD_RELOC_PPC64_ADDR16_HIGHERA34), (BFD_RELOC_PPC64_ADDR16_HIGHEST34, BFD_RELOC_PPC64_ADDR16_HIGHESTA34), (BFD_RELOC_PPC64_REL16_HIGHER34, BFD_RELOC_PPC64_REL16_HIGHERA34), (BFD_RELOC_PPC64_REL16_HIGHEST34, BFD_RELOC_PPC64_REL16_HIGHESTA34), (BFD_RELOC_PPC64_D28, BFD_RELOC_PPC64_PCREL28): New reloc enums. * elf64-ppc.c (PNOP): Define. (ppc64_elf_howto_raw): Add reloc howtos for new relocations. (ppc64_elf_reloc_type_lookup): Translate new bfd reloc numbers. (ppc64_elf_ha_reloc): Adjust addend for highera34 and highesta34 relocs. (ppc64_elf_prefix_reloc): New function. (struct ppc_link_hash_table): Add notoc_plt. (is_branch_reloc): Add R_PPC64_PLTCALL_NOTOC. (is_plt_seq_reloc): Add R_PPC64_PLT_PCREL34, R_PPC64_PLT_PCREL34_NOTOC, and R_PPC64_PLTSEQ_NOTOC. (ppc64_elf_check_relocs): Handle pcrel got and plt relocs. Set has_pltcall for section on seeing R_PPC64_PLTCALL_NOTOC. Handle possible need for dynamic relocs on non-pcrel powerxx relocs. (dec_dynrel_count): Handle non-pcrel powerxx relocs. (ppc64_elf_inline_plt): Handle R_PPC64_PLTCALL_NOTOC. (toc_adjusting_stub_needed): Likewise. (ppc64_elf_tls_optimize): Handle R_PPC64_PLTSEQ_NOTOC. (ppc64_elf_relocate_section): Handle new powerxx relocs. * bfd-in2.h: Regenerate. * libbfd.h: Regenerate. gas/ * config/tc-ppc.c (ppc_elf_suffix): Support @pcrel, @got@pcrel, @plt@pcrel, @higher34, @highera34, @highest34, and @highesta34. (fixup_size): Handle new powerxx relocs. (md_assemble): Warn for @pcrel on non-prefix insns. Accept @l, @h and @ha on prefix insns, and infer reloc without any @ suffix. Translate powerxx relocs to suit DQ and DS field instructions. Include operand tests as well as opcode test to translate BFD_RELOC_HI16_S to BFD_RELOC_PPC_16DX_HA. (ppc_fix_adjustable): Return false for pcrel GOT and PLT relocs. (md_apply_fix): Handle new powerxx relocs. * config/tc-ppc.h (TC_FORCE_RELOCATION_SUB_LOCAL): Accept BFD_RELOC_PPC64_ADDR16_HIGHER34, BFD_RELOC_PPC64_ADDR16_HIGHERA34, BFD_RELOC_PPC64_ADDR16_HIGHEST34, BFD_RELOC_PPC64_ADDR16_HIGHESTA34, BFD_RELOC_PPC64_D34, and BFD_RELOC_PPC64_D28. * testsuite/gas/ppc/prefix-reloc.d, * testsuite/gas/ppc/prefix-reloc.s: New test. * testsuite/gas/ppc/ppc.exp: Run it.
This commit is contained in:
parent
8acf14351c
commit
5663e32184
@ -1,3 +1,35 @@
|
||||
2019-05-24 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* reloc.c (BFD_RELOC_PPC64_D34, BFD_RELOC_PPC64_D34_LO),
|
||||
(BFD_RELOC_PPC64_D34_HI30, BFD_RELOC_PPC64_D34_HA30),
|
||||
(BFD_RELOC_PPC64_PCREL34, BFD_RELOC_PPC64_GOT_PCREL34),
|
||||
(BFD_RELOC_PPC64_PLT_PCREL34),
|
||||
(BFD_RELOC_PPC64_ADDR16_HIGHER34, BFD_RELOC_PPC64_ADDR16_HIGHERA34),
|
||||
(BFD_RELOC_PPC64_ADDR16_HIGHEST34, BFD_RELOC_PPC64_ADDR16_HIGHESTA34),
|
||||
(BFD_RELOC_PPC64_REL16_HIGHER34, BFD_RELOC_PPC64_REL16_HIGHERA34),
|
||||
(BFD_RELOC_PPC64_REL16_HIGHEST34, BFD_RELOC_PPC64_REL16_HIGHESTA34),
|
||||
(BFD_RELOC_PPC64_D28, BFD_RELOC_PPC64_PCREL28): New reloc enums.
|
||||
* elf64-ppc.c (PNOP): Define.
|
||||
(ppc64_elf_howto_raw): Add reloc howtos for new relocations.
|
||||
(ppc64_elf_reloc_type_lookup): Translate new bfd reloc numbers.
|
||||
(ppc64_elf_ha_reloc): Adjust addend for highera34 and highesta34
|
||||
relocs.
|
||||
(ppc64_elf_prefix_reloc): New function.
|
||||
(struct ppc_link_hash_table): Add notoc_plt.
|
||||
(is_branch_reloc): Add R_PPC64_PLTCALL_NOTOC.
|
||||
(is_plt_seq_reloc): Add R_PPC64_PLT_PCREL34,
|
||||
R_PPC64_PLT_PCREL34_NOTOC, and R_PPC64_PLTSEQ_NOTOC.
|
||||
(ppc64_elf_check_relocs): Handle pcrel got and plt relocs. Set
|
||||
has_pltcall for section on seeing R_PPC64_PLTCALL_NOTOC. Handle
|
||||
possible need for dynamic relocs on non-pcrel powerxx relocs.
|
||||
(dec_dynrel_count): Handle non-pcrel powerxx relocs.
|
||||
(ppc64_elf_inline_plt): Handle R_PPC64_PLTCALL_NOTOC.
|
||||
(toc_adjusting_stub_needed): Likewise.
|
||||
(ppc64_elf_tls_optimize): Handle R_PPC64_PLTSEQ_NOTOC.
|
||||
(ppc64_elf_relocate_section): Handle new powerxx relocs.
|
||||
* bfd-in2.h: Regenerate.
|
||||
* libbfd.h: Regenerate.
|
||||
|
||||
2019-05-23 Jose E. Marchesi <jose.marchesi@oracle.com>
|
||||
|
||||
* config.bfd (targ_cpu): Process bpf-*-none only if BFD64.
|
||||
|
@ -3498,6 +3498,23 @@ instruction. */
|
||||
BFD_RELOC_PPC64_ADDR64_LOCAL,
|
||||
BFD_RELOC_PPC64_ENTRY,
|
||||
BFD_RELOC_PPC64_REL24_NOTOC,
|
||||
BFD_RELOC_PPC64_D34,
|
||||
BFD_RELOC_PPC64_D34_LO,
|
||||
BFD_RELOC_PPC64_D34_HI30,
|
||||
BFD_RELOC_PPC64_D34_HA30,
|
||||
BFD_RELOC_PPC64_PCREL34,
|
||||
BFD_RELOC_PPC64_GOT_PCREL34,
|
||||
BFD_RELOC_PPC64_PLT_PCREL34,
|
||||
BFD_RELOC_PPC64_ADDR16_HIGHER34,
|
||||
BFD_RELOC_PPC64_ADDR16_HIGHERA34,
|
||||
BFD_RELOC_PPC64_ADDR16_HIGHEST34,
|
||||
BFD_RELOC_PPC64_ADDR16_HIGHESTA34,
|
||||
BFD_RELOC_PPC64_REL16_HIGHER34,
|
||||
BFD_RELOC_PPC64_REL16_HIGHERA34,
|
||||
BFD_RELOC_PPC64_REL16_HIGHEST34,
|
||||
BFD_RELOC_PPC64_REL16_HIGHESTA34,
|
||||
BFD_RELOC_PPC64_D28,
|
||||
BFD_RELOC_PPC64_PCREL28,
|
||||
|
||||
/* PowerPC and PowerPC64 thread-local storage relocations. */
|
||||
BFD_RELOC_PPC_TLS,
|
||||
|
409
bfd/elf64-ppc.c
409
bfd/elf64-ppc.c
@ -51,6 +51,8 @@ static bfd_reloc_status_type ppc64_elf_toc_ha_reloc
|
||||
(bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
|
||||
static bfd_reloc_status_type ppc64_elf_toc64_reloc
|
||||
(bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
|
||||
static bfd_reloc_status_type ppc64_elf_prefix_reloc
|
||||
(bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
|
||||
static bfd_reloc_status_type ppc64_elf_unhandled_reloc
|
||||
(bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
|
||||
static bfd_vma opd_entry_value
|
||||
@ -197,6 +199,7 @@ static bfd_vma opd_entry_value
|
||||
#define SLDI_R12_R12_32 0x799c07c6 /* sldi %r12,%r12,32 */
|
||||
#define LDX_R12_R11_R12 0x7d8b602a /* ldx %r12,%r11,%r12 */
|
||||
#define ADD_R12_R11_R12 0x7d8b6214 /* add %r12,%r11,%r12 */
|
||||
#define PNOP 0x0700000000000000ULL
|
||||
|
||||
/* __glink_PLTresolve stub instructions. We enter with the index in R0. */
|
||||
#define GLINK_PLTRESOLVE_SIZE(htab) \
|
||||
@ -878,6 +881,69 @@ static reloc_howto_type ppc64_elf_howto_raw[] =
|
||||
HOW (R_PPC64_ADDR64_LOCAL, 4, 64, 0xffffffffffffffffULL, 0, FALSE, dont,
|
||||
bfd_elf_generic_reloc),
|
||||
|
||||
HOW (R_PPC64_PLTSEQ_NOTOC, 2, 32, 0, 0, FALSE, dont,
|
||||
bfd_elf_generic_reloc),
|
||||
|
||||
HOW (R_PPC64_PLTCALL_NOTOC, 2, 32, 0, 0, FALSE, dont,
|
||||
bfd_elf_generic_reloc),
|
||||
|
||||
HOW (R_PPC64_PCREL_OPT, 2, 32, 0, 0, FALSE, dont,
|
||||
bfd_elf_generic_reloc),
|
||||
|
||||
HOW (R_PPC64_D34, 4, 34, 0x3ffff0000ffffULL, 0, FALSE, signed,
|
||||
ppc64_elf_prefix_reloc),
|
||||
|
||||
HOW (R_PPC64_D34_LO, 4, 34, 0x3ffff0000ffffULL, 0, FALSE, dont,
|
||||
ppc64_elf_prefix_reloc),
|
||||
|
||||
HOW (R_PPC64_D34_HI30, 4, 34, 0x3ffff0000ffffULL, 34, FALSE, dont,
|
||||
ppc64_elf_prefix_reloc),
|
||||
|
||||
HOW (R_PPC64_D34_HA30, 4, 34, 0x3ffff0000ffffULL, 34, FALSE, dont,
|
||||
ppc64_elf_prefix_reloc),
|
||||
|
||||
HOW (R_PPC64_PCREL34, 4, 34, 0x3ffff0000ffffULL, 0, TRUE, signed,
|
||||
ppc64_elf_prefix_reloc),
|
||||
|
||||
HOW (R_PPC64_GOT_PCREL34, 4, 34, 0x3ffff0000ffffULL, 0, TRUE, signed,
|
||||
ppc64_elf_unhandled_reloc),
|
||||
|
||||
HOW (R_PPC64_PLT_PCREL34, 4, 34, 0x3ffff0000ffffULL, 0, TRUE, signed,
|
||||
ppc64_elf_unhandled_reloc),
|
||||
|
||||
HOW (R_PPC64_PLT_PCREL34_NOTOC, 4, 34, 0x3ffff0000ffffULL, 0, TRUE, signed,
|
||||
ppc64_elf_unhandled_reloc),
|
||||
|
||||
HOW (R_PPC64_ADDR16_HIGHER34, 1, 16, 0xffff, 34, FALSE, dont,
|
||||
bfd_elf_generic_reloc),
|
||||
|
||||
HOW (R_PPC64_ADDR16_HIGHERA34, 1, 16, 0xffff, 34, FALSE, dont,
|
||||
ppc64_elf_ha_reloc),
|
||||
|
||||
HOW (R_PPC64_ADDR16_HIGHEST34, 1, 16, 0xffff, 50, FALSE, dont,
|
||||
bfd_elf_generic_reloc),
|
||||
|
||||
HOW (R_PPC64_ADDR16_HIGHESTA34, 1, 16, 0xffff, 50, FALSE, dont,
|
||||
ppc64_elf_ha_reloc),
|
||||
|
||||
HOW (R_PPC64_REL16_HIGHER34, 1, 16, 0xffff, 34, TRUE, dont,
|
||||
bfd_elf_generic_reloc),
|
||||
|
||||
HOW (R_PPC64_REL16_HIGHERA34, 1, 16, 0xffff, 34, TRUE, dont,
|
||||
ppc64_elf_ha_reloc),
|
||||
|
||||
HOW (R_PPC64_REL16_HIGHEST34, 1, 16, 0xffff, 50, TRUE, dont,
|
||||
bfd_elf_generic_reloc),
|
||||
|
||||
HOW (R_PPC64_REL16_HIGHESTA34, 1, 16, 0xffff, 50, TRUE, dont,
|
||||
ppc64_elf_ha_reloc),
|
||||
|
||||
HOW (R_PPC64_D28, 4, 28, 0xfff0000ffffULL, 0, FALSE, signed,
|
||||
ppc64_elf_prefix_reloc),
|
||||
|
||||
HOW (R_PPC64_PCREL28, 4, 28, 0xfff0000ffffULL, 0, TRUE, signed,
|
||||
ppc64_elf_prefix_reloc),
|
||||
|
||||
/* GNU extension to record C++ vtable hierarchy. */
|
||||
HOW (R_PPC64_GNU_VTINHERIT, 0, 0, 0, 0, FALSE, dont,
|
||||
NULL),
|
||||
@ -1167,6 +1233,40 @@ ppc64_elf_reloc_type_lookup (bfd *abfd,
|
||||
break;
|
||||
case BFD_RELOC_PPC64_ADDR64_LOCAL: r = R_PPC64_ADDR64_LOCAL;
|
||||
break;
|
||||
case BFD_RELOC_PPC64_D34: r = R_PPC64_D34;
|
||||
break;
|
||||
case BFD_RELOC_PPC64_D34_LO: r = R_PPC64_D34_LO;
|
||||
break;
|
||||
case BFD_RELOC_PPC64_D34_HI30: r = R_PPC64_D34_HI30;
|
||||
break;
|
||||
case BFD_RELOC_PPC64_D34_HA30: r = R_PPC64_D34_HA30;
|
||||
break;
|
||||
case BFD_RELOC_PPC64_PCREL34: r = R_PPC64_PCREL34;
|
||||
break;
|
||||
case BFD_RELOC_PPC64_GOT_PCREL34: r = R_PPC64_GOT_PCREL34;
|
||||
break;
|
||||
case BFD_RELOC_PPC64_PLT_PCREL34: r = R_PPC64_PLT_PCREL34;
|
||||
break;
|
||||
case BFD_RELOC_PPC64_ADDR16_HIGHER34: r = R_PPC64_ADDR16_HIGHER34;
|
||||
break;
|
||||
case BFD_RELOC_PPC64_ADDR16_HIGHERA34: r = R_PPC64_ADDR16_HIGHERA34;
|
||||
break;
|
||||
case BFD_RELOC_PPC64_ADDR16_HIGHEST34: r = R_PPC64_ADDR16_HIGHEST34;
|
||||
break;
|
||||
case BFD_RELOC_PPC64_ADDR16_HIGHESTA34: r = R_PPC64_ADDR16_HIGHESTA34;
|
||||
break;
|
||||
case BFD_RELOC_PPC64_REL16_HIGHER34: r = R_PPC64_REL16_HIGHER34;
|
||||
break;
|
||||
case BFD_RELOC_PPC64_REL16_HIGHERA34: r = R_PPC64_REL16_HIGHERA34;
|
||||
break;
|
||||
case BFD_RELOC_PPC64_REL16_HIGHEST34: r = R_PPC64_REL16_HIGHEST34;
|
||||
break;
|
||||
case BFD_RELOC_PPC64_REL16_HIGHESTA34: r = R_PPC64_REL16_HIGHESTA34;
|
||||
break;
|
||||
case BFD_RELOC_PPC64_D28: r = R_PPC64_D28;
|
||||
break;
|
||||
case BFD_RELOC_PPC64_PCREL28: r = R_PPC64_PCREL28;
|
||||
break;
|
||||
case BFD_RELOC_VTABLE_INHERIT: r = R_PPC64_GNU_VTINHERIT;
|
||||
break;
|
||||
case BFD_RELOC_VTABLE_ENTRY: r = R_PPC64_GNU_VTENTRY;
|
||||
@ -1243,11 +1343,17 @@ ppc64_elf_ha_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
|
||||
return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
|
||||
input_section, output_bfd, error_message);
|
||||
|
||||
/* Adjust the addend for sign extension of the low 16 bits.
|
||||
We won't actually be using the low 16 bits, so trashing them
|
||||
/* Adjust the addend for sign extension of the low 16 (or 34) bits.
|
||||
We won't actually be using the low bits, so trashing them
|
||||
doesn't matter. */
|
||||
reloc_entry->addend += 0x8000;
|
||||
r_type = reloc_entry->howto->type;
|
||||
if (r_type == R_PPC64_ADDR16_HIGHERA34
|
||||
|| r_type == R_PPC64_ADDR16_HIGHESTA34
|
||||
|| r_type == R_PPC64_REL16_HIGHERA34
|
||||
|| r_type == R_PPC64_REL16_HIGHESTA34)
|
||||
reloc_entry->addend += 1ULL << 33;
|
||||
else
|
||||
reloc_entry->addend += 1U << 15;
|
||||
if (r_type != R_PPC64_REL16DX_HA)
|
||||
return bfd_reloc_continue;
|
||||
|
||||
@ -1492,6 +1598,48 @@ ppc64_elf_toc64_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
|
||||
return bfd_reloc_ok;
|
||||
}
|
||||
|
||||
static bfd_reloc_status_type
|
||||
ppc64_elf_prefix_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
|
||||
void *data, asection *input_section,
|
||||
bfd *output_bfd, char **error_message)
|
||||
{
|
||||
uint64_t insn;
|
||||
bfd_vma targ;
|
||||
|
||||
if (output_bfd != NULL)
|
||||
return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
|
||||
input_section, output_bfd, error_message);
|
||||
|
||||
insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
|
||||
insn <<= 32;
|
||||
insn |= bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address + 4);
|
||||
|
||||
targ = (symbol->section->output_section->vma
|
||||
+ symbol->section->output_offset
|
||||
+ reloc_entry->addend);
|
||||
if (!bfd_is_com_section (symbol->section))
|
||||
targ += symbol->value;
|
||||
if (reloc_entry->howto->type == R_PPC64_D34_HA30)
|
||||
targ += 1ULL << 33;
|
||||
if (reloc_entry->howto->pc_relative)
|
||||
{
|
||||
bfd_vma from = (reloc_entry->address
|
||||
+ input_section->output_offset
|
||||
+ input_section->output_section->vma);
|
||||
targ -=from;
|
||||
}
|
||||
targ >>= reloc_entry->howto->rightshift;
|
||||
insn &= ~reloc_entry->howto->dst_mask;
|
||||
insn |= ((targ << 16) | (targ & 0xffff)) & reloc_entry->howto->dst_mask;
|
||||
bfd_put_32 (abfd, insn >> 32, (bfd_byte *) data + reloc_entry->address);
|
||||
bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address + 4);
|
||||
if (reloc_entry->howto->complain_on_overflow == complain_overflow_signed
|
||||
&& (targ + (1ULL << (reloc_entry->howto->bitsize - 1))
|
||||
>= 1ULL << reloc_entry->howto->bitsize))
|
||||
return bfd_reloc_overflow;
|
||||
return bfd_reloc_ok;
|
||||
}
|
||||
|
||||
static bfd_reloc_status_type
|
||||
ppc64_elf_unhandled_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
|
||||
void *data, asection *input_section,
|
||||
@ -2981,6 +3129,9 @@ struct ppc_link_hash_table
|
||||
/* Whether plt calls for ELFv2 localentry:0 funcs have been optimized. */
|
||||
unsigned int has_plt_localentry0:1;
|
||||
|
||||
/* Whether calls are made via the PLT from NOTOC functions. */
|
||||
unsigned int notoc_plt:1;
|
||||
|
||||
/* Incremented every time we size stubs. */
|
||||
unsigned int stub_iteration;
|
||||
|
||||
@ -4235,7 +4386,8 @@ is_branch_reloc (enum elf_ppc64_reloc_type r_type)
|
||||
|| r_type == R_PPC64_ADDR14
|
||||
|| r_type == R_PPC64_ADDR14_BRTAKEN
|
||||
|| r_type == R_PPC64_ADDR14_BRNTAKEN
|
||||
|| r_type == R_PPC64_PLTCALL);
|
||||
|| r_type == R_PPC64_PLTCALL
|
||||
|| r_type == R_PPC64_PLTCALL_NOTOC);
|
||||
}
|
||||
|
||||
/* Relocs on inline plt call sequence insns prior to the call. */
|
||||
@ -4247,7 +4399,10 @@ is_plt_seq_reloc (enum elf_ppc64_reloc_type r_type)
|
||||
|| r_type == R_PPC64_PLT16_HI
|
||||
|| r_type == R_PPC64_PLT16_LO
|
||||
|| r_type == R_PPC64_PLT16_LO_DS
|
||||
|| r_type == R_PPC64_PLTSEQ);
|
||||
|| r_type == R_PPC64_PLT_PCREL34
|
||||
|| r_type == R_PPC64_PLT_PCREL34_NOTOC
|
||||
|| r_type == R_PPC64_PLTSEQ
|
||||
|| r_type == R_PPC64_PLTSEQ_NOTOC);
|
||||
}
|
||||
|
||||
/* Look through the relocs for a section during the first phase, and
|
||||
@ -4302,6 +4457,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
||||
int tls_type;
|
||||
struct _ppc64_elf_section_data *ppc64_sec;
|
||||
struct plt_entry **ifunc, **plt_list;
|
||||
bfd_vma sym_addend;
|
||||
|
||||
r_symndx = ELF64_R_SYM (rel->r_info);
|
||||
if (r_symndx < symtab_hdr->sh_info)
|
||||
@ -4317,6 +4473,24 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
||||
|
||||
tls_type = 0;
|
||||
ifunc = NULL;
|
||||
r_type = ELF64_R_TYPE (rel->r_info);
|
||||
switch (r_type)
|
||||
{
|
||||
default:
|
||||
/* Somewhat foolishly, because the ABIs don't specifically
|
||||
allow it, ppc64 gas and ld support GOT and PLT relocs
|
||||
with non-zero addends where the addend results in
|
||||
sym+addend being stored in the GOT or PLT entry. This
|
||||
can't be supported for pcrel relocs because the addend is
|
||||
used to specify the pcrel offset. */
|
||||
sym_addend = rel->r_addend;
|
||||
break;
|
||||
case R_PPC64_GOT_PCREL34:
|
||||
case R_PPC64_PLT_PCREL34:
|
||||
case R_PPC64_PLT_PCREL34_NOTOC:
|
||||
sym_addend = 0;
|
||||
break;
|
||||
}
|
||||
if (h != NULL)
|
||||
{
|
||||
if (h->type == STT_GNU_IFUNC)
|
||||
@ -4335,14 +4509,13 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
||||
if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
|
||||
{
|
||||
ifunc = update_local_sym_info (abfd, symtab_hdr, r_symndx,
|
||||
rel->r_addend,
|
||||
sym_addend,
|
||||
NON_GOT | PLT_IFUNC);
|
||||
if (ifunc == NULL)
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
r_type = ELF64_R_TYPE (rel->r_info);
|
||||
switch (r_type)
|
||||
{
|
||||
case R_PPC64_TLSGD:
|
||||
@ -4353,7 +4526,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
||||
((struct ppc_link_hash_entry *) h)->tls_mask |= TLS_TLS | TLS_MARK;
|
||||
else
|
||||
if (!update_local_sym_info (abfd, symtab_hdr, r_symndx,
|
||||
rel->r_addend,
|
||||
sym_addend,
|
||||
NON_GOT | TLS_TLS | TLS_MARK))
|
||||
return FALSE;
|
||||
sec->has_tls_reloc = 1;
|
||||
@ -4401,6 +4574,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
||||
case R_PPC64_GOT16:
|
||||
case R_PPC64_GOT16_HI:
|
||||
case R_PPC64_GOT16_LO:
|
||||
case R_PPC64_GOT_PCREL34:
|
||||
dogot:
|
||||
/* This symbol requires a global offset table entry. */
|
||||
sec->has_toc_reloc = 1;
|
||||
@ -4426,7 +4600,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
||||
|
||||
eh = (struct ppc_link_hash_entry *) h;
|
||||
for (ent = eh->elf.got.glist; ent != NULL; ent = ent->next)
|
||||
if (ent->addend == rel->r_addend
|
||||
if (ent->addend == sym_addend
|
||||
&& ent->owner == abfd
|
||||
&& ent->tls_type == tls_type)
|
||||
break;
|
||||
@ -4437,7 +4611,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
||||
if (ent == NULL)
|
||||
return FALSE;
|
||||
ent->next = eh->elf.got.glist;
|
||||
ent->addend = rel->r_addend;
|
||||
ent->addend = sym_addend;
|
||||
ent->owner = abfd;
|
||||
ent->tls_type = tls_type;
|
||||
ent->is_indirect = FALSE;
|
||||
@ -4450,14 +4624,14 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
||||
else
|
||||
/* This is a global offset table entry for a local symbol. */
|
||||
if (!update_local_sym_info (abfd, symtab_hdr, r_symndx,
|
||||
rel->r_addend, tls_type))
|
||||
sym_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))
|
||||
if (!update_plt_info (abfd, &h->plt.plist, sym_addend))
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
@ -4466,6 +4640,8 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
||||
case R_PPC64_PLT16_HI:
|
||||
case R_PPC64_PLT16_LO:
|
||||
case R_PPC64_PLT16_LO_DS:
|
||||
case R_PPC64_PLT_PCREL34:
|
||||
case R_PPC64_PLT_PCREL34_NOTOC:
|
||||
case R_PPC64_PLT32:
|
||||
case R_PPC64_PLT64:
|
||||
/* This symbol requires a procedure linkage table entry. */
|
||||
@ -4481,9 +4657,9 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
||||
}
|
||||
if (plt_list == NULL)
|
||||
plt_list = update_local_sym_info (abfd, symtab_hdr, r_symndx,
|
||||
rel->r_addend,
|
||||
sym_addend,
|
||||
NON_GOT | PLT_KEEP);
|
||||
if (!update_plt_info (abfd, plt_list, rel->r_addend))
|
||||
if (!update_plt_info (abfd, plt_list, sym_addend))
|
||||
return FALSE;
|
||||
break;
|
||||
|
||||
@ -4521,6 +4697,10 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
||||
case R_PPC64_REL16_HIGHERA:
|
||||
case R_PPC64_REL16_HIGHEST:
|
||||
case R_PPC64_REL16_HIGHESTA:
|
||||
case R_PPC64_REL16_HIGHER34:
|
||||
case R_PPC64_REL16_HIGHERA34:
|
||||
case R_PPC64_REL16_HIGHEST34:
|
||||
case R_PPC64_REL16_HIGHESTA34:
|
||||
case R_PPC64_REL16DX_HA:
|
||||
break;
|
||||
|
||||
@ -4603,6 +4783,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
||||
goto rel24;
|
||||
|
||||
case R_PPC64_PLTCALL:
|
||||
case R_PPC64_PLTCALL_NOTOC:
|
||||
ppc64_elf_section_data (sec)->has_pltcall = 1;
|
||||
/* Fall through. */
|
||||
|
||||
@ -4636,7 +4817,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
||||
/* We may need a .plt entry if the function this reloc
|
||||
refers to is in a shared lib. */
|
||||
if (plt_list
|
||||
&& !update_plt_info (abfd, plt_list, rel->r_addend))
|
||||
&& !update_plt_info (abfd, plt_list, sym_addend))
|
||||
return FALSE;
|
||||
break;
|
||||
|
||||
@ -4680,7 +4861,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
||||
}
|
||||
else
|
||||
if (!update_local_sym_info (abfd, symtab_hdr, r_symndx,
|
||||
rel->r_addend, tls_type))
|
||||
sym_addend, tls_type))
|
||||
return FALSE;
|
||||
|
||||
ppc64_sec = ppc64_elf_section_data (sec);
|
||||
@ -4702,7 +4883,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
||||
}
|
||||
BFD_ASSERT (rel->r_offset % 8 == 0);
|
||||
ppc64_sec->u.toc.symndx[rel->r_offset / 8] = r_symndx;
|
||||
ppc64_sec->u.toc.add[rel->r_offset / 8] = rel->r_addend;
|
||||
ppc64_sec->u.toc.add[rel->r_offset / 8] = sym_addend;
|
||||
|
||||
/* Mark the second slot of a GD or LD entry.
|
||||
-1 to indicate GD and -2 to indicate LD. */
|
||||
@ -4750,12 +4931,21 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
||||
case R_PPC64_ADDR16_HIGHESTA:
|
||||
case R_PPC64_ADDR16_LO:
|
||||
case R_PPC64_ADDR16_LO_DS:
|
||||
case R_PPC64_D34:
|
||||
case R_PPC64_D34_LO:
|
||||
case R_PPC64_D34_HI30:
|
||||
case R_PPC64_D34_HA30:
|
||||
case R_PPC64_ADDR16_HIGHER34:
|
||||
case R_PPC64_ADDR16_HIGHERA34:
|
||||
case R_PPC64_ADDR16_HIGHEST34:
|
||||
case R_PPC64_ADDR16_HIGHESTA34:
|
||||
case R_PPC64_D28:
|
||||
if (h != NULL && !bfd_link_pic (info) && abiversion (abfd) != 1
|
||||
&& rel->r_addend == 0)
|
||||
{
|
||||
/* We may need a .plt entry if this reloc refers to a
|
||||
function in a shared lib. */
|
||||
if (!update_plt_info (abfd, &h->plt.plist, rel->r_addend))
|
||||
if (!update_plt_info (abfd, &h->plt.plist, 0))
|
||||
return FALSE;
|
||||
h->pointer_equality_needed = 1;
|
||||
}
|
||||
@ -6562,6 +6752,15 @@ dec_dynrel_count (bfd_vma r_info,
|
||||
case R_PPC64_UADDR32:
|
||||
case R_PPC64_UADDR64:
|
||||
case R_PPC64_TOC:
|
||||
case R_PPC64_D34:
|
||||
case R_PPC64_D34_LO:
|
||||
case R_PPC64_D34_HI30:
|
||||
case R_PPC64_D34_HA30:
|
||||
case R_PPC64_ADDR16_HIGHER34:
|
||||
case R_PPC64_ADDR16_HIGHERA34:
|
||||
case R_PPC64_ADDR16_HIGHEST34:
|
||||
case R_PPC64_ADDR16_HIGHESTA34:
|
||||
case R_PPC64_D28:
|
||||
break;
|
||||
}
|
||||
|
||||
@ -7167,7 +7366,8 @@ ppc64_elf_inline_plt (struct bfd_link_info *info)
|
||||
unsigned char *tls_maskp;
|
||||
|
||||
r_type = ELF64_R_TYPE (rel->r_info);
|
||||
if (r_type != R_PPC64_PLTCALL)
|
||||
if (r_type != R_PPC64_PLTCALL
|
||||
&& r_type != R_PPC64_PLTCALL_NOTOC)
|
||||
continue;
|
||||
|
||||
r_symndx = ELF64_R_SYM (rel->r_info);
|
||||
@ -7195,7 +7395,11 @@ ppc64_elf_inline_plt (struct bfd_link_info *info)
|
||||
from = (rel->r_offset
|
||||
+ sec->output_offset
|
||||
+ sec->output_section->vma);
|
||||
if (to - from + limit < 2 * limit)
|
||||
if (to - from + limit < 2 * limit
|
||||
&& !(r_type == R_PPC64_PLTCALL_NOTOC
|
||||
&& (((h ? h->other : sym->st_other)
|
||||
& STO_PPC64_LOCAL_MASK)
|
||||
!= 1 << STO_PPC64_LOCAL_BIT)))
|
||||
*tls_maskp &= ~PLT_KEEP;
|
||||
}
|
||||
}
|
||||
@ -7574,7 +7778,9 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info)
|
||||
{
|
||||
if (pass != 0
|
||||
&& (ELF64_R_TYPE (rel[1].r_info)
|
||||
!= R_PPC64_PLTSEQ))
|
||||
!= R_PPC64_PLTSEQ)
|
||||
&& (ELF64_R_TYPE (rel[1].r_info)
|
||||
!= R_PPC64_PLTSEQ_NOTOC))
|
||||
{
|
||||
r_symndx = ELF64_R_SYM (rel[1].r_info);
|
||||
if (!get_sym_h (&h, NULL, NULL, NULL, &locsyms,
|
||||
@ -11631,7 +11837,8 @@ toc_adjusting_stub_needed (struct bfd_link_info *info, asection *isec)
|
||||
&& r_type != R_PPC64_REL14
|
||||
&& r_type != R_PPC64_REL14_BRTAKEN
|
||||
&& r_type != R_PPC64_REL14_BRNTAKEN
|
||||
&& r_type != R_PPC64_PLTCALL)
|
||||
&& r_type != R_PPC64_PLTCALL
|
||||
&& r_type != R_PPC64_PLTCALL_NOTOC)
|
||||
continue;
|
||||
|
||||
r_symndx = ELF64_R_SYM (rel->r_info);
|
||||
@ -14030,10 +14237,14 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
{
|
||||
unsigned int insn2;
|
||||
bfd_vma offset = rel->r_offset;
|
||||
enum elf_ppc64_reloc_type r_type1 = ELF64_R_TYPE (rel[1].r_info);
|
||||
|
||||
if (is_plt_seq_reloc (ELF64_R_TYPE (rel[1].r_info)))
|
||||
if (is_plt_seq_reloc (r_type1))
|
||||
{
|
||||
bfd_put_32 (output_bfd, NOP, contents + offset);
|
||||
if (r_type1 == R_PPC64_PLT_PCREL34
|
||||
|| r_type1 == R_PPC64_PLT_PCREL34_NOTOC)
|
||||
bfd_put_32 (output_bfd, NOP, contents + offset + 4);
|
||||
rel[1].r_info = ELF64_R_INFO (STN_UNDEF, R_PPC64_NONE);
|
||||
break;
|
||||
}
|
||||
@ -14075,10 +14286,14 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
{
|
||||
unsigned int insn2;
|
||||
bfd_vma offset = rel->r_offset;
|
||||
enum elf_ppc64_reloc_type r_type1 = ELF64_R_TYPE (rel[1].r_info);
|
||||
|
||||
if (is_plt_seq_reloc (ELF64_R_TYPE (rel[1].r_info)))
|
||||
if (is_plt_seq_reloc (r_type1))
|
||||
{
|
||||
bfd_put_32 (output_bfd, NOP, contents + offset);
|
||||
if (r_type1 == R_PPC64_PLT_PCREL34
|
||||
|| r_type1 == R_PPC64_PLT_PCREL34_NOTOC)
|
||||
bfd_put_32 (output_bfd, NOP, contents + offset + 4);
|
||||
rel[1].r_info = ELF64_R_INFO (STN_UNDEF, R_PPC64_NONE);
|
||||
break;
|
||||
}
|
||||
@ -14279,6 +14494,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
case R_PPC64_REL24:
|
||||
case R_PPC64_REL24_NOTOC:
|
||||
case R_PPC64_PLTCALL:
|
||||
case R_PPC64_PLTCALL_NOTOC:
|
||||
/* Calls to functions with a different TOC, such as calls to
|
||||
shared objects, need to alter the TOC pointer. This is
|
||||
done using a linkage stub. A REL24 branching to these
|
||||
@ -14292,7 +14508,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
fdh = ppc_follow_link (h->oh);
|
||||
stub_entry = ppc_get_stub_entry (input_section, sec, fdh, &orig_rel,
|
||||
htab);
|
||||
if (r_type == R_PPC64_PLTCALL
|
||||
if ((r_type == R_PPC64_PLTCALL
|
||||
|| r_type == R_PPC64_PLTCALL_NOTOC)
|
||||
&& stub_entry != NULL
|
||||
&& stub_entry->stub_type >= ppc_stub_plt_call
|
||||
&& stub_entry->stub_type <= ppc_stub_plt_call_both)
|
||||
@ -14522,6 +14739,11 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
|| stub_entry->stub_type == ppc_stub_plt_call_both)
|
||||
&& r_type == R_PPC64_REL24_NOTOC)
|
||||
relocation += 4;
|
||||
|
||||
if (r_type == R_PPC64_REL24_NOTOC
|
||||
&& (stub_entry->stub_type == ppc_stub_plt_call_notoc
|
||||
|| stub_entry->stub_type == ppc_stub_plt_call_both))
|
||||
htab->notoc_plt = 1;
|
||||
}
|
||||
|
||||
if (insn != 0)
|
||||
@ -14665,6 +14887,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
case R_PPC64_GOT16_HA:
|
||||
case R_PPC64_GOT16_DS:
|
||||
case R_PPC64_GOT16_LO_DS:
|
||||
case R_PPC64_GOT_PCREL34:
|
||||
dogot:
|
||||
{
|
||||
/* Relocation is to the entry for this symbol in the global
|
||||
@ -14674,6 +14897,10 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
bfd_vma off;
|
||||
unsigned long indx = 0;
|
||||
struct got_entry *ent;
|
||||
bfd_vma sym_addend = orig_rel.r_addend;
|
||||
|
||||
if (r_type == R_PPC64_GOT_PCREL34)
|
||||
sym_addend = 0;
|
||||
|
||||
if (tls_type == (TLS_TLS | TLS_LD)
|
||||
&& (h == NULL
|
||||
@ -14707,7 +14934,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
}
|
||||
|
||||
for (; ent != NULL; ent = ent->next)
|
||||
if (ent->addend == orig_rel.r_addend
|
||||
if (ent->addend == sym_addend
|
||||
&& ent->owner == input_bfd
|
||||
&& ent->tls_type == tls_type)
|
||||
break;
|
||||
@ -14764,7 +14991,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
outrel.r_offset = (got->output_section->vma
|
||||
+ got->output_offset
|
||||
+ off);
|
||||
outrel.r_addend = addend;
|
||||
outrel.r_addend = sym_addend;
|
||||
if (tls_type & (TLS_LD | TLS_GD))
|
||||
{
|
||||
outrel.r_addend = 0;
|
||||
@ -14777,7 +15004,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
bfd_elf64_swap_reloca_out (output_bfd,
|
||||
&outrel, loc);
|
||||
outrel.r_offset += 8;
|
||||
outrel.r_addend = addend;
|
||||
outrel.r_addend = sym_addend;
|
||||
outrel.r_info
|
||||
= ELF64_R_INFO (indx, R_PPC64_DTPREL64);
|
||||
}
|
||||
@ -14823,7 +15050,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
emitting a reloc. */
|
||||
else
|
||||
{
|
||||
relocation += addend;
|
||||
relocation += sym_addend;
|
||||
if (tls_type != 0)
|
||||
{
|
||||
if (htab->elf.tls_sec == NULL)
|
||||
@ -14854,7 +15081,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
abort ();
|
||||
|
||||
relocation = got->output_section->vma + got->output_offset + off;
|
||||
addend = -(TOCstart + htab->sec_info[input_section->id].toc_off);
|
||||
if (r_type != R_PPC64_GOT_PCREL34)
|
||||
addend = -(TOCstart + htab->sec_info[input_section->id].toc_off);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -14862,10 +15090,14 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
case R_PPC64_PLT16_HI:
|
||||
case R_PPC64_PLT16_LO:
|
||||
case R_PPC64_PLT16_LO_DS:
|
||||
case R_PPC64_PLT_PCREL34:
|
||||
case R_PPC64_PLT_PCREL34_NOTOC:
|
||||
case R_PPC64_PLT32:
|
||||
case R_PPC64_PLT64:
|
||||
case R_PPC64_PLTSEQ:
|
||||
case R_PPC64_PLTSEQ_NOTOC:
|
||||
case R_PPC64_PLTCALL:
|
||||
case R_PPC64_PLTCALL_NOTOC:
|
||||
/* Relocation is to the entry for this symbol in the
|
||||
procedure linkage table. */
|
||||
unresolved_reloc = TRUE;
|
||||
@ -14882,10 +15114,15 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
if (plt_list)
|
||||
{
|
||||
struct plt_entry *ent;
|
||||
bfd_vma sym_addend = orig_rel.r_addend;
|
||||
|
||||
if (r_type == R_PPC64_PLT_PCREL34
|
||||
|| r_type == R_PPC64_PLT_PCREL34_NOTOC)
|
||||
sym_addend = 0;
|
||||
|
||||
for (ent = *plt_list; ent != NULL; ent = ent->next)
|
||||
if (ent->plt.offset != (bfd_vma) -1
|
||||
&& ent->addend == orig_rel.r_addend)
|
||||
&& ent->addend == sym_addend)
|
||||
{
|
||||
asection *plt;
|
||||
bfd_vma got;
|
||||
@ -14914,7 +15151,9 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
+ htab->sec_info[input_section->id].toc_off);
|
||||
relocation -= got;
|
||||
}
|
||||
addend = 0;
|
||||
if (r_type != R_PPC64_PLT_PCREL34
|
||||
&& r_type != R_PPC64_PLT_PCREL34_NOTOC)
|
||||
addend = 0;
|
||||
unresolved_reloc = FALSE;
|
||||
break;
|
||||
}
|
||||
@ -14969,14 +15208,18 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
case R_PPC64_REL16_HIGHERA:
|
||||
case R_PPC64_REL16_HIGHEST:
|
||||
case R_PPC64_REL16_HIGHESTA:
|
||||
case R_PPC64_REL16_HIGHER34:
|
||||
case R_PPC64_REL16_HIGHERA34:
|
||||
case R_PPC64_REL16_HIGHEST34:
|
||||
case R_PPC64_REL16_HIGHESTA34:
|
||||
case R_PPC64_REL16DX_HA:
|
||||
break;
|
||||
|
||||
case R_PPC64_REL14:
|
||||
case R_PPC64_REL14_BRNTAKEN:
|
||||
case R_PPC64_REL14_BRTAKEN:
|
||||
case R_PPC64_REL24:
|
||||
case R_PPC64_REL24_NOTOC:
|
||||
case R_PPC64_PCREL34:
|
||||
case R_PPC64_PCREL28:
|
||||
break;
|
||||
|
||||
case R_PPC64_TPREL16:
|
||||
@ -15071,12 +15314,21 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
case R_PPC64_ADDR16_HIGHESTA:
|
||||
case R_PPC64_ADDR16_LO:
|
||||
case R_PPC64_ADDR16_LO_DS:
|
||||
case R_PPC64_ADDR16_HIGHER34:
|
||||
case R_PPC64_ADDR16_HIGHERA34:
|
||||
case R_PPC64_ADDR16_HIGHEST34:
|
||||
case R_PPC64_ADDR16_HIGHESTA34:
|
||||
case R_PPC64_ADDR24:
|
||||
case R_PPC64_ADDR32:
|
||||
case R_PPC64_ADDR64:
|
||||
case R_PPC64_UADDR16:
|
||||
case R_PPC64_UADDR32:
|
||||
case R_PPC64_UADDR64:
|
||||
case R_PPC64_D34:
|
||||
case R_PPC64_D34_LO:
|
||||
case R_PPC64_D34_HI30:
|
||||
case R_PPC64_D34_HA30:
|
||||
case R_PPC64_D28:
|
||||
dodyn:
|
||||
if ((input_section->flags & SEC_ALLOC) == 0)
|
||||
break;
|
||||
@ -15328,6 +15580,10 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
insn. */
|
||||
break;
|
||||
|
||||
case R_PPC64_PLTCALL_NOTOC:
|
||||
if (!unresolved_reloc)
|
||||
htab->notoc_plt = 1;
|
||||
/* Fall through. */
|
||||
case R_PPC64_PLTCALL:
|
||||
if (unresolved_reloc)
|
||||
{
|
||||
@ -15336,12 +15592,14 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
insn = bfd_get_32 (input_bfd, p);
|
||||
insn &= 1;
|
||||
bfd_put_32 (input_bfd, B_DOT | insn, p);
|
||||
bfd_put_32 (input_bfd, NOP, p + 4);
|
||||
if (r_type == R_PPC64_PLTCALL)
|
||||
bfd_put_32 (input_bfd, NOP, p + 4);
|
||||
unresolved_reloc = save_unresolved_reloc;
|
||||
r_type = R_PPC64_REL24;
|
||||
}
|
||||
break;
|
||||
|
||||
case R_PPC64_PLTSEQ_NOTOC:
|
||||
case R_PPC64_PLTSEQ:
|
||||
if (unresolved_reloc)
|
||||
{
|
||||
@ -15350,6 +15608,21 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
}
|
||||
break;
|
||||
|
||||
case R_PPC64_PLT_PCREL34_NOTOC:
|
||||
if (!unresolved_reloc)
|
||||
htab->notoc_plt = 1;
|
||||
/* Fall through. */
|
||||
case R_PPC64_PLT_PCREL34:
|
||||
if (unresolved_reloc)
|
||||
{
|
||||
bfd_byte *p = contents + rel->r_offset;
|
||||
bfd_put_32 (input_bfd, PNOP >> 32, p);
|
||||
bfd_put_32 (input_bfd, PNOP, p + 4);
|
||||
unresolved_reloc = FALSE;
|
||||
goto copy_reloc;
|
||||
}
|
||||
break;
|
||||
|
||||
case R_PPC64_PLT16_HA:
|
||||
if (unresolved_reloc)
|
||||
{
|
||||
@ -15488,6 +15761,15 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
addend += 0x8000;
|
||||
break;
|
||||
|
||||
case R_PPC64_D34_HA30:
|
||||
case R_PPC64_ADDR16_HIGHERA34:
|
||||
case R_PPC64_ADDR16_HIGHESTA34:
|
||||
case R_PPC64_REL16_HIGHERA34:
|
||||
case R_PPC64_REL16_HIGHESTA34:
|
||||
if (sec != NULL)
|
||||
addend += 1ULL << 33;
|
||||
break;
|
||||
|
||||
case R_PPC64_ADDR16_DS:
|
||||
case R_PPC64_ADDR16_LO_DS:
|
||||
case R_PPC64_GOT16_DS:
|
||||
@ -15583,9 +15865,50 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
}
|
||||
}
|
||||
|
||||
if (r_type == R_PPC64_REL16DX_HA)
|
||||
switch (r_type)
|
||||
{
|
||||
/* Split field reloc isn't handled by _bfd_final_link_relocate. */
|
||||
/* Split field relocs aren't handled by _bfd_final_link_relocate. */
|
||||
case R_PPC64_D34:
|
||||
case R_PPC64_D34_LO:
|
||||
case R_PPC64_D34_HI30:
|
||||
case R_PPC64_D34_HA30:
|
||||
case R_PPC64_PCREL34:
|
||||
case R_PPC64_GOT_PCREL34:
|
||||
case R_PPC64_PLT_PCREL34:
|
||||
case R_PPC64_PLT_PCREL34_NOTOC:
|
||||
case R_PPC64_D28:
|
||||
case R_PPC64_PCREL28:
|
||||
if (rel->r_offset + 8 > input_section->size)
|
||||
r = bfd_reloc_outofrange;
|
||||
else
|
||||
{
|
||||
uint64_t pinsn;
|
||||
|
||||
relocation += addend;
|
||||
if (howto->pc_relative)
|
||||
relocation -= (rel->r_offset
|
||||
+ input_section->output_offset
|
||||
+ input_section->output_section->vma);
|
||||
relocation >>= howto->rightshift;
|
||||
|
||||
pinsn = bfd_get_32 (input_bfd, contents + rel->r_offset);
|
||||
pinsn <<= 32;
|
||||
pinsn |= bfd_get_32 (input_bfd, contents + rel->r_offset + 4);
|
||||
|
||||
pinsn &= ~howto->dst_mask;
|
||||
pinsn |= (((relocation << 16) | (relocation & 0xffff))
|
||||
& howto->dst_mask);
|
||||
bfd_put_32 (input_bfd, pinsn >> 32, contents + rel->r_offset);
|
||||
bfd_put_32 (input_bfd, pinsn, contents + rel->r_offset + 4);
|
||||
r = bfd_reloc_ok;
|
||||
if (howto->complain_on_overflow == complain_overflow_signed
|
||||
&& (relocation + (1ULL << (howto->bitsize - 1))
|
||||
>= 1ULL << howto->bitsize))
|
||||
r = bfd_reloc_overflow;
|
||||
}
|
||||
break;
|
||||
|
||||
case R_PPC64_REL16DX_HA:
|
||||
if (rel->r_offset + 4 > input_section->size)
|
||||
r = bfd_reloc_outofrange;
|
||||
else
|
||||
@ -15603,10 +15926,13 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
if (relocation + 0x8000 > 0xffff)
|
||||
r = bfd_reloc_overflow;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
r = _bfd_final_link_relocate (howto, input_bfd, input_section,
|
||||
contents, rel->r_offset,
|
||||
relocation, addend);
|
||||
}
|
||||
else
|
||||
r = _bfd_final_link_relocate (howto, input_bfd, input_section, contents,
|
||||
rel->r_offset, relocation, addend);
|
||||
|
||||
if (r != bfd_reloc_ok)
|
||||
{
|
||||
@ -15884,7 +16210,8 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd,
|
||||
break;
|
||||
|
||||
case DT_PPC64_OPT:
|
||||
if (htab->do_multi_toc && htab->multi_toc_needed)
|
||||
if ((htab->do_multi_toc && htab->multi_toc_needed)
|
||||
|| htab->notoc_plt)
|
||||
dyn.d_un.d_val |= PPC64_OPT_MULTI_TOC;
|
||||
if (htab->has_plt_localentry0)
|
||||
dyn.d_un.d_val |= PPC64_OPT_LOCALENTRY;
|
||||
|
17
bfd/libbfd.h
17
bfd/libbfd.h
@ -1476,6 +1476,23 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
|
||||
"BFD_RELOC_PPC64_ADDR64_LOCAL",
|
||||
"BFD_RELOC_PPC64_ENTRY",
|
||||
"BFD_RELOC_PPC64_REL24_NOTOC",
|
||||
"BFD_RELOC_PPC64_D34",
|
||||
"BFD_RELOC_PPC64_D34_LO",
|
||||
"BFD_RELOC_PPC64_D34_HI30",
|
||||
"BFD_RELOC_PPC64_D34_HA30",
|
||||
"BFD_RELOC_PPC64_PCREL34",
|
||||
"BFD_RELOC_PPC64_GOT_PCREL34",
|
||||
"BFD_RELOC_PPC64_PLT_PCREL34",
|
||||
"BFD_RELOC_PPC64_ADDR16_HIGHER34",
|
||||
"BFD_RELOC_PPC64_ADDR16_HIGHERA34",
|
||||
"BFD_RELOC_PPC64_ADDR16_HIGHEST34",
|
||||
"BFD_RELOC_PPC64_ADDR16_HIGHESTA34",
|
||||
"BFD_RELOC_PPC64_REL16_HIGHER34",
|
||||
"BFD_RELOC_PPC64_REL16_HIGHERA34",
|
||||
"BFD_RELOC_PPC64_REL16_HIGHEST34",
|
||||
"BFD_RELOC_PPC64_REL16_HIGHESTA34",
|
||||
"BFD_RELOC_PPC64_D28",
|
||||
"BFD_RELOC_PPC64_PCREL28",
|
||||
"BFD_RELOC_PPC_TLS",
|
||||
"BFD_RELOC_PPC_TLSGD",
|
||||
"BFD_RELOC_PPC_TLSLD",
|
||||
|
34
bfd/reloc.c
34
bfd/reloc.c
@ -2878,6 +2878,40 @@ ENUMX
|
||||
BFD_RELOC_PPC64_ENTRY
|
||||
ENUMX
|
||||
BFD_RELOC_PPC64_REL24_NOTOC
|
||||
ENUMX
|
||||
BFD_RELOC_PPC64_D34
|
||||
ENUMX
|
||||
BFD_RELOC_PPC64_D34_LO
|
||||
ENUMX
|
||||
BFD_RELOC_PPC64_D34_HI30
|
||||
ENUMX
|
||||
BFD_RELOC_PPC64_D34_HA30
|
||||
ENUMX
|
||||
BFD_RELOC_PPC64_PCREL34
|
||||
ENUMX
|
||||
BFD_RELOC_PPC64_GOT_PCREL34
|
||||
ENUMX
|
||||
BFD_RELOC_PPC64_PLT_PCREL34
|
||||
ENUMX
|
||||
BFD_RELOC_PPC64_ADDR16_HIGHER34
|
||||
ENUMX
|
||||
BFD_RELOC_PPC64_ADDR16_HIGHERA34
|
||||
ENUMX
|
||||
BFD_RELOC_PPC64_ADDR16_HIGHEST34
|
||||
ENUMX
|
||||
BFD_RELOC_PPC64_ADDR16_HIGHESTA34
|
||||
ENUMX
|
||||
BFD_RELOC_PPC64_REL16_HIGHER34
|
||||
ENUMX
|
||||
BFD_RELOC_PPC64_REL16_HIGHERA34
|
||||
ENUMX
|
||||
BFD_RELOC_PPC64_REL16_HIGHEST34
|
||||
ENUMX
|
||||
BFD_RELOC_PPC64_REL16_HIGHESTA34
|
||||
ENUMX
|
||||
BFD_RELOC_PPC64_D28
|
||||
ENUMX
|
||||
BFD_RELOC_PPC64_PCREL28
|
||||
ENUMDOC
|
||||
Power(rs6000) and PowerPC relocations.
|
||||
|
||||
|
@ -1,3 +1,23 @@
|
||||
2019-05-24 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* config/tc-ppc.c (ppc_elf_suffix): Support @pcrel, @got@pcrel,
|
||||
@plt@pcrel, @higher34, @highera34, @highest34, and @highesta34.
|
||||
(fixup_size): Handle new powerxx relocs.
|
||||
(md_assemble): Warn for @pcrel on non-prefix insns.
|
||||
Accept @l, @h and @ha on prefix insns, and infer reloc without
|
||||
any @ suffix. Translate powerxx relocs to suit DQ and DS field
|
||||
instructions. Include operand tests as well as opcode test to
|
||||
translate BFD_RELOC_HI16_S to BFD_RELOC_PPC_16DX_HA.
|
||||
(ppc_fix_adjustable): Return false for pcrel GOT and PLT relocs.
|
||||
(md_apply_fix): Handle new powerxx relocs.
|
||||
* config/tc-ppc.h (TC_FORCE_RELOCATION_SUB_LOCAL): Accept
|
||||
BFD_RELOC_PPC64_ADDR16_HIGHER34, BFD_RELOC_PPC64_ADDR16_HIGHERA34,
|
||||
BFD_RELOC_PPC64_ADDR16_HIGHEST34, BFD_RELOC_PPC64_ADDR16_HIGHESTA34,
|
||||
BFD_RELOC_PPC64_D34, and BFD_RELOC_PPC64_D28.
|
||||
* testsuite/gas/ppc/prefix-reloc.d,
|
||||
* testsuite/gas/ppc/prefix-reloc.s: New test.
|
||||
* testsuite/gas/ppc/ppc.exp: Run it.
|
||||
|
||||
2019-05-24 Peter Bergner <bergner@linux.ibm.com>
|
||||
Alan Modra <amodra@gmail.com>
|
||||
|
||||
|
@ -2151,6 +2151,13 @@ ppc_elf_suffix (char **str_p, expressionS *exp_p)
|
||||
MAP64 ("tprel@highest", BFD_RELOC_PPC64_TPREL16_HIGHEST),
|
||||
MAP64 ("tprel@highesta", BFD_RELOC_PPC64_TPREL16_HIGHESTA),
|
||||
MAP64 ("notoc", BFD_RELOC_PPC64_REL24_NOTOC),
|
||||
MAP64 ("pcrel", BFD_RELOC_PPC64_PCREL34),
|
||||
MAP64 ("got@pcrel", BFD_RELOC_PPC64_GOT_PCREL34),
|
||||
MAP64 ("plt@pcrel", BFD_RELOC_PPC64_PLT_PCREL34),
|
||||
MAP64 ("higher34", BFD_RELOC_PPC64_ADDR16_HIGHER34),
|
||||
MAP64 ("highera34", BFD_RELOC_PPC64_ADDR16_HIGHERA34),
|
||||
MAP64 ("highest34", BFD_RELOC_PPC64_ADDR16_HIGHEST34),
|
||||
MAP64 ("highesta34", BFD_RELOC_PPC64_ADDR16_HIGHESTA34),
|
||||
{ (char *) 0, 0, 0, 0, BFD_RELOC_NONE }
|
||||
};
|
||||
|
||||
@ -2931,6 +2938,10 @@ fixup_size (bfd_reloc_code_real_type reloc, bfd_boolean *pc_relative)
|
||||
case BFD_RELOC_PPC64_ADDR16_DS:
|
||||
case BFD_RELOC_PPC64_ADDR16_HIGH:
|
||||
case BFD_RELOC_PPC64_ADDR16_HIGHA:
|
||||
case BFD_RELOC_PPC64_ADDR16_HIGHER34:
|
||||
case BFD_RELOC_PPC64_ADDR16_HIGHERA34:
|
||||
case BFD_RELOC_PPC64_ADDR16_HIGHEST34:
|
||||
case BFD_RELOC_PPC64_ADDR16_HIGHESTA34:
|
||||
case BFD_RELOC_PPC64_ADDR16_LO_DS:
|
||||
case BFD_RELOC_PPC64_DTPREL16_DS:
|
||||
case BFD_RELOC_PPC64_DTPREL16_HIGH:
|
||||
@ -3018,9 +3029,13 @@ fixup_size (bfd_reloc_code_real_type reloc, bfd_boolean *pc_relative)
|
||||
case BFD_RELOC_PPC64_REL16_HIGH:
|
||||
case BFD_RELOC_PPC64_REL16_HIGHA:
|
||||
case BFD_RELOC_PPC64_REL16_HIGHER:
|
||||
case BFD_RELOC_PPC64_REL16_HIGHER34:
|
||||
case BFD_RELOC_PPC64_REL16_HIGHERA:
|
||||
case BFD_RELOC_PPC64_REL16_HIGHERA34:
|
||||
case BFD_RELOC_PPC64_REL16_HIGHEST:
|
||||
case BFD_RELOC_PPC64_REL16_HIGHEST34:
|
||||
case BFD_RELOC_PPC64_REL16_HIGHESTA:
|
||||
case BFD_RELOC_PPC64_REL16_HIGHESTA34:
|
||||
#ifdef OBJ_XCOFF
|
||||
case BFD_RELOC_PPC_B16:
|
||||
#endif
|
||||
@ -3100,12 +3115,21 @@ fixup_size (bfd_reloc_code_real_type reloc, bfd_boolean *pc_relative)
|
||||
case BFD_RELOC_64:
|
||||
case BFD_RELOC_64_PLTOFF:
|
||||
case BFD_RELOC_PPC64_ADDR64_LOCAL:
|
||||
case BFD_RELOC_PPC64_D28:
|
||||
case BFD_RELOC_PPC64_D34:
|
||||
case BFD_RELOC_PPC64_D34_LO:
|
||||
case BFD_RELOC_PPC64_D34_HI30:
|
||||
case BFD_RELOC_PPC64_D34_HA30:
|
||||
case BFD_RELOC_PPC64_TOC:
|
||||
size = 8;
|
||||
break;
|
||||
|
||||
case BFD_RELOC_64_PCREL:
|
||||
case BFD_RELOC_64_PLT_PCREL:
|
||||
case BFD_RELOC_PPC64_GOT_PCREL34:
|
||||
case BFD_RELOC_PPC64_PCREL28:
|
||||
case BFD_RELOC_PPC64_PCREL34:
|
||||
case BFD_RELOC_PPC64_PLT_PCREL34:
|
||||
size = 8;
|
||||
pcrel = TRUE;
|
||||
break;
|
||||
@ -3665,24 +3689,47 @@ md_assemble (char *str)
|
||||
reloc = BFD_RELOC_PPC_TPREL16;
|
||||
break;
|
||||
|
||||
case BFD_RELOC_LO16:
|
||||
if ((operand->bitm | 0xf) != 0xffff
|
||||
|| operand->shift != 0
|
||||
case BFD_RELOC_PPC64_PCREL34:
|
||||
if (operand->bitm == 0xfffffffULL)
|
||||
{
|
||||
reloc = BFD_RELOC_PPC64_PCREL28;
|
||||
break;
|
||||
}
|
||||
/* Fall through. */
|
||||
case BFD_RELOC_PPC64_GOT_PCREL34:
|
||||
case BFD_RELOC_PPC64_PLT_PCREL34:
|
||||
if (operand->bitm != 0x3ffffffffULL
|
||||
|| (operand->flags & PPC_OPERAND_NEGATIVE) != 0)
|
||||
as_warn (_("%s unsupported on this instruction"), "@pcrel");
|
||||
break;
|
||||
|
||||
case BFD_RELOC_LO16:
|
||||
if (operand->bitm == 0x3ffffffffULL
|
||||
&& (operand->flags & PPC_OPERAND_NEGATIVE) == 0)
|
||||
reloc = BFD_RELOC_PPC64_D34_LO;
|
||||
else if ((operand->bitm | 0xf) != 0xffff
|
||||
|| operand->shift != 0
|
||||
|| (operand->flags & PPC_OPERAND_NEGATIVE) != 0)
|
||||
as_warn (_("%s unsupported on this instruction"), "@l");
|
||||
break;
|
||||
|
||||
case BFD_RELOC_HI16:
|
||||
if (operand->bitm != 0xffff
|
||||
|| operand->shift != 0
|
||||
|| (operand->flags & PPC_OPERAND_NEGATIVE) != 0)
|
||||
if (operand->bitm == 0x3ffffffffULL
|
||||
&& (operand->flags & PPC_OPERAND_NEGATIVE) == 0)
|
||||
reloc = BFD_RELOC_PPC64_D34_HI30;
|
||||
else if (operand->bitm != 0xffff
|
||||
|| operand->shift != 0
|
||||
|| (operand->flags & PPC_OPERAND_NEGATIVE) != 0)
|
||||
as_warn (_("%s unsupported on this instruction"), "@h");
|
||||
break;
|
||||
|
||||
case BFD_RELOC_HI16_S:
|
||||
if (operand->bitm == 0xffff
|
||||
&& operand->shift == (int) PPC_OPSHIFT_INV
|
||||
&& opcode->opcode == (19 << 26) + (2 << 1))
|
||||
if (operand->bitm == 0x3ffffffffULL
|
||||
&& (operand->flags & PPC_OPERAND_NEGATIVE) == 0)
|
||||
reloc = BFD_RELOC_PPC64_D34_HA30;
|
||||
else if (operand->bitm == 0xffff
|
||||
&& operand->shift == (int) PPC_OPSHIFT_INV
|
||||
&& opcode->opcode == (19 << 26) + (2 << 1))
|
||||
/* addpcis. */
|
||||
reloc = BFD_RELOC_PPC_16DX_HA;
|
||||
else if (operand->bitm != 0xffff
|
||||
@ -3738,6 +3785,10 @@ md_assemble (char *str)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (operand->bitm == 0x3ffffffffULL)
|
||||
reloc = BFD_RELOC_PPC64_D34;
|
||||
else if (operand->bitm == 0xfffffffULL)
|
||||
reloc = BFD_RELOC_PPC64_D28;
|
||||
|
||||
/* For the absolute forms of branches, convert the PC
|
||||
relative form back into the absolute. */
|
||||
@ -3787,53 +3838,69 @@ md_assemble (char *str)
|
||||
case BFD_RELOC_16:
|
||||
reloc = BFD_RELOC_PPC64_ADDR16_DS;
|
||||
break;
|
||||
|
||||
case BFD_RELOC_LO16:
|
||||
reloc = BFD_RELOC_PPC64_ADDR16_LO_DS;
|
||||
break;
|
||||
|
||||
case BFD_RELOC_16_GOTOFF:
|
||||
reloc = BFD_RELOC_PPC64_GOT16_DS;
|
||||
break;
|
||||
|
||||
case BFD_RELOC_LO16_GOTOFF:
|
||||
reloc = BFD_RELOC_PPC64_GOT16_LO_DS;
|
||||
break;
|
||||
|
||||
case BFD_RELOC_LO16_PLTOFF:
|
||||
reloc = BFD_RELOC_PPC64_PLT16_LO_DS;
|
||||
break;
|
||||
|
||||
case BFD_RELOC_16_BASEREL:
|
||||
reloc = BFD_RELOC_PPC64_SECTOFF_DS;
|
||||
break;
|
||||
|
||||
case BFD_RELOC_LO16_BASEREL:
|
||||
reloc = BFD_RELOC_PPC64_SECTOFF_LO_DS;
|
||||
break;
|
||||
|
||||
case BFD_RELOC_PPC_TOC16:
|
||||
reloc = BFD_RELOC_PPC64_TOC16_DS;
|
||||
break;
|
||||
|
||||
case BFD_RELOC_PPC64_TOC16_LO:
|
||||
reloc = BFD_RELOC_PPC64_TOC16_LO_DS;
|
||||
break;
|
||||
|
||||
case BFD_RELOC_PPC64_PLTGOT16:
|
||||
reloc = BFD_RELOC_PPC64_PLTGOT16_DS;
|
||||
break;
|
||||
|
||||
case BFD_RELOC_PPC64_PLTGOT16_LO:
|
||||
reloc = BFD_RELOC_PPC64_PLTGOT16_LO_DS;
|
||||
break;
|
||||
|
||||
case BFD_RELOC_PPC_DTPREL16:
|
||||
reloc = BFD_RELOC_PPC64_DTPREL16_DS;
|
||||
break;
|
||||
|
||||
case BFD_RELOC_PPC_DTPREL16_LO:
|
||||
reloc = BFD_RELOC_PPC64_DTPREL16_LO_DS;
|
||||
break;
|
||||
|
||||
case BFD_RELOC_PPC_TPREL16:
|
||||
reloc = BFD_RELOC_PPC64_TPREL16_DS;
|
||||
break;
|
||||
|
||||
case BFD_RELOC_PPC_TPREL16_LO:
|
||||
reloc = BFD_RELOC_PPC64_TPREL16_LO_DS;
|
||||
break;
|
||||
|
||||
case BFD_RELOC_PPC_GOT_DTPREL16:
|
||||
case BFD_RELOC_PPC_GOT_DTPREL16_LO:
|
||||
case BFD_RELOC_PPC_GOT_TPREL16:
|
||||
case BFD_RELOC_PPC_GOT_TPREL16_LO:
|
||||
break;
|
||||
|
||||
default:
|
||||
as_bad (_("unsupported relocation for DS offset field"));
|
||||
break;
|
||||
@ -6903,6 +6970,7 @@ ppc_fix_adjustable (fixS *fix)
|
||||
&& fix->fx_r_type != BFD_RELOC_PPC64_GOT16_LO_DS
|
||||
&& fix->fx_r_type != BFD_RELOC_16_GOT_PCREL
|
||||
&& fix->fx_r_type != BFD_RELOC_32_GOTOFF
|
||||
&& fix->fx_r_type != BFD_RELOC_PPC64_GOT_PCREL34
|
||||
&& fix->fx_r_type != BFD_RELOC_24_PLT_PCREL
|
||||
&& fix->fx_r_type != BFD_RELOC_32_PLTOFF
|
||||
&& fix->fx_r_type != BFD_RELOC_32_PLT_PCREL
|
||||
@ -6912,6 +6980,7 @@ ppc_fix_adjustable (fixS *fix)
|
||||
&& fix->fx_r_type != BFD_RELOC_64_PLTOFF
|
||||
&& fix->fx_r_type != BFD_RELOC_64_PLT_PCREL
|
||||
&& fix->fx_r_type != BFD_RELOC_PPC64_PLT16_LO_DS
|
||||
&& fix->fx_r_type != BFD_RELOC_PPC64_PLT_PCREL34
|
||||
&& fix->fx_r_type != BFD_RELOC_PPC64_PLTGOT16
|
||||
&& fix->fx_r_type != BFD_RELOC_PPC64_PLTGOT16_LO
|
||||
&& fix->fx_r_type != BFD_RELOC_PPC64_PLTGOT16_HI
|
||||
@ -7120,10 +7189,34 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
|
||||
fixP->fx_r_type = BFD_RELOC_PPC64_REL16_HIGHESTA;
|
||||
break;
|
||||
|
||||
case BFD_RELOC_PPC64_ADDR16_HIGHER34:
|
||||
fixP->fx_r_type = BFD_RELOC_PPC64_REL16_HIGHER34;
|
||||
break;
|
||||
|
||||
case BFD_RELOC_PPC64_ADDR16_HIGHERA34:
|
||||
fixP->fx_r_type = BFD_RELOC_PPC64_REL16_HIGHERA34;
|
||||
break;
|
||||
|
||||
case BFD_RELOC_PPC64_ADDR16_HIGHEST34:
|
||||
fixP->fx_r_type = BFD_RELOC_PPC64_REL16_HIGHEST34;
|
||||
break;
|
||||
|
||||
case BFD_RELOC_PPC64_ADDR16_HIGHESTA34:
|
||||
fixP->fx_r_type = BFD_RELOC_PPC64_REL16_HIGHESTA34;
|
||||
break;
|
||||
|
||||
case BFD_RELOC_PPC_16DX_HA:
|
||||
fixP->fx_r_type = BFD_RELOC_PPC_REL16DX_HA;
|
||||
break;
|
||||
|
||||
case BFD_RELOC_PPC64_D34:
|
||||
fixP->fx_r_type = BFD_RELOC_PPC64_PCREL34;
|
||||
break;
|
||||
|
||||
case BFD_RELOC_PPC64_D28:
|
||||
fixP->fx_r_type = BFD_RELOC_PPC64_PCREL28;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -7370,6 +7463,8 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
|
||||
case BFD_RELOC_PPC_VLE_SDAREL_HI16D:
|
||||
case BFD_RELOC_PPC_VLE_SDAREL_HA16A:
|
||||
case BFD_RELOC_PPC_VLE_SDAREL_HA16D:
|
||||
case BFD_RELOC_PPC64_GOT_PCREL34:
|
||||
case BFD_RELOC_PPC64_PLT_PCREL34:
|
||||
gas_assert (fixP->fx_addsy != NULL);
|
||||
/* Fallthru */
|
||||
|
||||
@ -7421,9 +7516,12 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
|
||||
#else
|
||||
#define APPLY_RELOC 1
|
||||
#endif
|
||||
/* We need to call the insert function even when fieldval is
|
||||
zero if the insert function would translate that zero to a
|
||||
bit pattern other than all zeros. */
|
||||
if ((fieldval != 0 && APPLY_RELOC) || operand->insert != NULL)
|
||||
{
|
||||
unsigned long insn;
|
||||
uint64_t insn;
|
||||
unsigned char *where;
|
||||
|
||||
/* Fetch the instruction, insert the fully resolved operand
|
||||
@ -7431,34 +7529,56 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
|
||||
where = (unsigned char *) fixP->fx_frag->fr_literal + fixP->fx_where;
|
||||
if (target_big_endian)
|
||||
{
|
||||
if (fixP->fx_size == 4)
|
||||
insn = bfd_getb32 (where);
|
||||
else
|
||||
if (fixP->fx_size < 4)
|
||||
insn = bfd_getb16 (where);
|
||||
else
|
||||
{
|
||||
insn = bfd_getb32 (where);
|
||||
if (fixP->fx_size > 4)
|
||||
insn = insn << 32 | bfd_getb32 (where + 4);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fixP->fx_size == 4)
|
||||
insn = bfd_getl32 (where);
|
||||
else
|
||||
if (fixP->fx_size < 4)
|
||||
insn = bfd_getl16 (where);
|
||||
else
|
||||
{
|
||||
insn = bfd_getl32 (where);
|
||||
if (fixP->fx_size > 4)
|
||||
insn = insn << 32 | bfd_getl32 (where + 4);
|
||||
}
|
||||
}
|
||||
insn = ppc_insert_operand (insn, operand, fieldval,
|
||||
fixP->tc_fix_data.ppc_cpu,
|
||||
fixP->fx_file, fixP->fx_line);
|
||||
if (target_big_endian)
|
||||
{
|
||||
if (fixP->fx_size == 4)
|
||||
bfd_putb32 (insn, where);
|
||||
else
|
||||
if (fixP->fx_size < 4)
|
||||
bfd_putb16 (insn, where);
|
||||
else
|
||||
{
|
||||
if (fixP->fx_size > 4)
|
||||
{
|
||||
bfd_putb32 (insn, where + 4);
|
||||
insn >>= 32;
|
||||
}
|
||||
bfd_putb32 (insn, where);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fixP->fx_size == 4)
|
||||
bfd_putl32 (insn, where);
|
||||
else
|
||||
if (fixP->fx_size < 4)
|
||||
bfd_putl16 (insn, where);
|
||||
else
|
||||
{
|
||||
if (fixP->fx_size > 4)
|
||||
{
|
||||
bfd_putl32 (insn, where + 4);
|
||||
insn >>= 32;
|
||||
}
|
||||
bfd_putl32 (insn, where);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -273,7 +273,13 @@ extern int ppc_force_relocation (struct fix *);
|
||||
|| (FIX)->fx_r_type == BFD_RELOC_PPC64_HIGHER_S \
|
||||
|| (FIX)->fx_r_type == BFD_RELOC_PPC64_HIGHEST \
|
||||
|| (FIX)->fx_r_type == BFD_RELOC_PPC64_HIGHEST_S \
|
||||
|| (FIX)->fx_r_type == BFD_RELOC_PPC_16DX_HA))
|
||||
|| (FIX)->fx_r_type == BFD_RELOC_PPC64_ADDR16_HIGHER34 \
|
||||
|| (FIX)->fx_r_type == BFD_RELOC_PPC64_ADDR16_HIGHERA34 \
|
||||
|| (FIX)->fx_r_type == BFD_RELOC_PPC64_ADDR16_HIGHEST34 \
|
||||
|| (FIX)->fx_r_type == BFD_RELOC_PPC64_ADDR16_HIGHESTA34 \
|
||||
|| (FIX)->fx_r_type == BFD_RELOC_PPC_16DX_HA \
|
||||
|| (FIX)->fx_r_type == BFD_RELOC_PPC64_D34 \
|
||||
|| (FIX)->fx_r_type == BFD_RELOC_PPC64_D28))
|
||||
#endif
|
||||
|
||||
#define TC_VALIDATE_FIX_SUB(FIX, SEG) 0
|
||||
|
@ -116,3 +116,4 @@ run_dump_test "htm"
|
||||
run_dump_test "titan"
|
||||
run_dump_test "prefix-align"
|
||||
run_dump_test "prefix-pcrel"
|
||||
run_dump_test "prefix-reloc"
|
||||
|
35
gas/testsuite/gas/ppc/prefix-reloc.d
Normal file
35
gas/testsuite/gas/ppc/prefix-reloc.d
Normal file
@ -0,0 +1,35 @@
|
||||
#as: -a64 -mfuture
|
||||
#objdump: -dr -Mfuture
|
||||
#name: Prefix insn relocations
|
||||
|
||||
.*
|
||||
|
||||
Disassembly of section \.text:
|
||||
|
||||
0+ <\.text>:
|
||||
0: (00 00 00 06|06 00 00 00) pli r9,0
|
||||
4: (00 00 20 39|39 20 00 00)
|
||||
0: R_PPC64_D34_HA30 ext
|
||||
8: (46 17 29 79|79 29 17 46) rldicr r9,r9,34,29
|
||||
c: (00 00 00 06|06 00 00 00) paddi r9,r9,0
|
||||
10: (00 00 29 39|39 29 00 00)
|
||||
c: R_PPC64_D34_LO ext
|
||||
14: (00 00 10 04|04 10 00 00) pld r3,0
|
||||
18: (00 00 60 e4|e4 60 00 00)
|
||||
14: R_PPC64_PCREL34 ext
|
||||
1c: (00 00 10 04|04 10 00 00) pld r4,0
|
||||
20: (00 00 80 e4|e4 80 00 00)
|
||||
1c: R_PPC64_GOT_PCREL34 ext
|
||||
24: (00 00 10 04|04 10 00 00) pld r5,0
|
||||
28: (00 00 a0 e4|e4 a0 00 00)
|
||||
24: R_PPC64_PLT_PCREL34 ext
|
||||
2c: (00 00 10 04|04 10 00 00) pld r6,0
|
||||
30: (00 00 c0 e4|e4 c0 00 00)
|
||||
2c: R_PPC64_PCREL34 ext
|
||||
34: (00 00 00 04|04 00 00 00) pld r7,0\(0\)
|
||||
38: (00 00 e0 e4|e4 e0 00 00)
|
||||
34: R_PPC64_D34 ext
|
||||
3c: (00 00 00 60|60 00 00 00) nop
|
||||
40: (00 00 10 04|04 10 00 00) pld r8,0
|
||||
44: (00 00 00 e5|e5 00 00 00)
|
||||
40: R_PPC64_PCREL34 ext
|
13
gas/testsuite/gas/ppc/prefix-reloc.s
Normal file
13
gas/testsuite/gas/ppc/prefix-reloc.s
Normal file
@ -0,0 +1,13 @@
|
||||
.text
|
||||
pli 9,ext@ha
|
||||
sldi 9,9,34
|
||||
paddi 9,9,ext@l
|
||||
pld 3,ext@pcrel
|
||||
pld 4,ext@got@pcrel
|
||||
pld 5,ext@plt@pcrel
|
||||
0: pld 6,ext-0b(0),1
|
||||
pld 7,ext(0),0
|
||||
# The following insn will need an alignment nop, testing the behaviour
|
||||
# of "dot" in the expression. Don't stupidly edit this file and lose
|
||||
# the nop.
|
||||
pld 8,ext-.(0),1
|
@ -1,3 +1,15 @@
|
||||
2019-05-24 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* elf/ppc64.h (R_PPC64_PLTSEQ_NOTOC, R_PPC64_PLTCALL_NOTOC),
|
||||
(R_PPC64_PCREL_OPT, R_PPC64_D34, R_PPC64_D34_LO, R_PPC64_D34_HI30),
|
||||
(R_PPC64_D34_HA30, R_PPC64_PCREL34, R_PPC64_GOT_PCREL34),
|
||||
(R_PPC64_PLT_PCREL34, R_PPC64_PLT_PCREL34_NOTOC),
|
||||
(R_PPC64_ADDR16_HIGHER34, R_PPC64_ADDR16_HIGHERA34),
|
||||
(R_PPC64_ADDR16_HIGHEST34, R_PPC64_ADDR16_HIGHESTA34),
|
||||
(R_PPC64_REL16_HIGHER34, R_PPC64_REL16_HIGHERA34),
|
||||
(R_PPC64_REL16_HIGHEST34, R_PPC64_REL16_HIGHESTA34),
|
||||
(R_PPC64_D28, R_PPC64_PCREL28): Define.
|
||||
|
||||
2019-05-24 Peter Bergner <bergner@linux.ibm.com>
|
||||
Alan Modra <amodra@gmail.com>
|
||||
|
||||
|
@ -158,6 +158,30 @@ START_RELOC_NUMBERS (elf_ppc64_reloc_type)
|
||||
RELOC_NUMBER (R_PPC64_PLTSEQ, 119)
|
||||
RELOC_NUMBER (R_PPC64_PLTCALL, 120)
|
||||
|
||||
/* Powerxx support. */
|
||||
RELOC_NUMBER (R_PPC64_PLTSEQ_NOTOC, 121)
|
||||
RELOC_NUMBER (R_PPC64_PLTCALL_NOTOC, 122)
|
||||
RELOC_NUMBER (R_PPC64_PCREL_OPT, 123)
|
||||
|
||||
RELOC_NUMBER (R_PPC64_D34, 128)
|
||||
RELOC_NUMBER (R_PPC64_D34_LO, 129)
|
||||
RELOC_NUMBER (R_PPC64_D34_HI30, 130)
|
||||
RELOC_NUMBER (R_PPC64_D34_HA30, 131)
|
||||
RELOC_NUMBER (R_PPC64_PCREL34, 132)
|
||||
RELOC_NUMBER (R_PPC64_GOT_PCREL34, 133)
|
||||
RELOC_NUMBER (R_PPC64_PLT_PCREL34, 134)
|
||||
RELOC_NUMBER (R_PPC64_PLT_PCREL34_NOTOC, 135)
|
||||
RELOC_NUMBER (R_PPC64_ADDR16_HIGHER34, 136)
|
||||
RELOC_NUMBER (R_PPC64_ADDR16_HIGHERA34, 137)
|
||||
RELOC_NUMBER (R_PPC64_ADDR16_HIGHEST34, 138)
|
||||
RELOC_NUMBER (R_PPC64_ADDR16_HIGHESTA34, 139)
|
||||
RELOC_NUMBER (R_PPC64_REL16_HIGHER34, 140)
|
||||
RELOC_NUMBER (R_PPC64_REL16_HIGHERA34, 141)
|
||||
RELOC_NUMBER (R_PPC64_REL16_HIGHEST34, 142)
|
||||
RELOC_NUMBER (R_PPC64_REL16_HIGHESTA34, 143)
|
||||
RELOC_NUMBER (R_PPC64_D28, 144)
|
||||
RELOC_NUMBER (R_PPC64_PCREL28, 145)
|
||||
|
||||
#ifndef RELOC_MACROS_GEN_FUNC
|
||||
/* Relocation only used internally by gas or ld. If you need to use
|
||||
these reloc numbers, you can change them to some other unused value
|
||||
|
Loading…
Reference in New Issue
Block a user