PR target/14758

bfd/
	* elf32-ppc.c (ppc_elf_reloc_type_lookup): Decode ppc64 _DS
	bfd_reloc values.  Map to corresponding D-form relocs.
	(is_insn_ds_form, is_insn_qs_form): New functions.
	(ppc_elf_relocate_section): Validate insn with DS-form or DQ-form
	fields using D-form reloc.
gas/
	* config/tc-ppc.c (ppc_setup_opcodes): Fix comment.
	(md_assemble): Translate to _DS relocs for ppc32 as well as ppc64.
	(tc_gen_reloc): Handle _DS relocs in ppc32 mode.
This commit is contained in:
Alan Modra 2012-10-26 03:40:37 +00:00
parent e3b0b0abf9
commit 1fe532cf60
4 changed files with 93 additions and 3 deletions

View file

@ -1,3 +1,12 @@
2012-10-26 Alan Modra <amodra@gmail.com>
PR target/14758
* elf32-ppc.c (ppc_elf_reloc_type_lookup): Decode ppc64 _DS
bfd_reloc values. Map to corresponding D-form relocs.
(is_insn_ds_form, is_insn_qs_form): New functions.
(ppc_elf_relocate_section): Validate insn with DS-form or DQ-form
fields using D-form reloc.
2012-10-25 H.J. Lu <hongjiu.lu@intel.com>
* elf32-i386.c (elf_i386_size_dynamic_sections): Replace

View file

@ -1815,7 +1815,9 @@ ppc_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
case BFD_RELOC_NONE: r = R_PPC_NONE; break;
case BFD_RELOC_32: r = R_PPC_ADDR32; break;
case BFD_RELOC_PPC_BA26: r = R_PPC_ADDR24; break;
case BFD_RELOC_PPC64_ADDR16_DS:
case BFD_RELOC_16: r = R_PPC_ADDR16; break;
case BFD_RELOC_PPC64_ADDR16_LO_DS:
case BFD_RELOC_LO16: r = R_PPC_ADDR16_LO; break;
case BFD_RELOC_HI16: r = R_PPC_ADDR16_HI; break;
case BFD_RELOC_HI16_S: r = R_PPC_ADDR16_HA; break;
@ -1826,7 +1828,9 @@ ppc_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
case BFD_RELOC_PPC_B16: r = R_PPC_REL14; break;
case BFD_RELOC_PPC_B16_BRTAKEN: r = R_PPC_REL14_BRTAKEN; break;
case BFD_RELOC_PPC_B16_BRNTAKEN: r = R_PPC_REL14_BRNTAKEN; break;
case BFD_RELOC_PPC64_GOT16_DS:
case BFD_RELOC_16_GOTOFF: r = R_PPC_GOT16; break;
case BFD_RELOC_PPC64_GOT16_LO_DS:
case BFD_RELOC_LO16_GOTOFF: r = R_PPC_GOT16_LO; break;
case BFD_RELOC_HI16_GOTOFF: r = R_PPC_GOT16_HI; break;
case BFD_RELOC_HI16_S_GOTOFF: r = R_PPC_GOT16_HA; break;
@ -1837,26 +1841,34 @@ ppc_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
case BFD_RELOC_32_PCREL: r = R_PPC_REL32; break;
case BFD_RELOC_32_PLTOFF: r = R_PPC_PLT32; break;
case BFD_RELOC_32_PLT_PCREL: r = R_PPC_PLTREL32; break;
case BFD_RELOC_PPC64_PLT16_LO_DS:
case BFD_RELOC_LO16_PLTOFF: r = R_PPC_PLT16_LO; break;
case BFD_RELOC_HI16_PLTOFF: r = R_PPC_PLT16_HI; break;
case BFD_RELOC_HI16_S_PLTOFF: r = R_PPC_PLT16_HA; break;
case BFD_RELOC_GPREL16: r = R_PPC_SDAREL16; break;
case BFD_RELOC_PPC64_SECTOFF_DS:
case BFD_RELOC_16_BASEREL: r = R_PPC_SECTOFF; break;
case BFD_RELOC_PPC64_SECTOFF_LO_DS:
case BFD_RELOC_LO16_BASEREL: r = R_PPC_SECTOFF_LO; break;
case BFD_RELOC_HI16_BASEREL: r = R_PPC_SECTOFF_HI; break;
case BFD_RELOC_HI16_S_BASEREL: r = R_PPC_SECTOFF_HA; break;
case BFD_RELOC_CTOR: r = R_PPC_ADDR32; break;
case BFD_RELOC_PPC64_TOC16_DS:
case BFD_RELOC_PPC_TOC16: r = R_PPC_TOC16; break;
case BFD_RELOC_PPC_TLS: r = R_PPC_TLS; break;
case BFD_RELOC_PPC_TLSGD: r = R_PPC_TLSGD; break;
case BFD_RELOC_PPC_TLSLD: r = R_PPC_TLSLD; break;
case BFD_RELOC_PPC_DTPMOD: r = R_PPC_DTPMOD32; break;
case BFD_RELOC_PPC64_TPREL16_DS:
case BFD_RELOC_PPC_TPREL16: r = R_PPC_TPREL16; break;
case BFD_RELOC_PPC64_TPREL16_LO_DS:
case BFD_RELOC_PPC_TPREL16_LO: r = R_PPC_TPREL16_LO; break;
case BFD_RELOC_PPC_TPREL16_HI: r = R_PPC_TPREL16_HI; break;
case BFD_RELOC_PPC_TPREL16_HA: r = R_PPC_TPREL16_HA; break;
case BFD_RELOC_PPC_TPREL: r = R_PPC_TPREL32; break;
case BFD_RELOC_PPC64_DTPREL16_DS:
case BFD_RELOC_PPC_DTPREL16: r = R_PPC_DTPREL16; break;
case BFD_RELOC_PPC64_DTPREL16_LO_DS:
case BFD_RELOC_PPC_DTPREL16_LO: r = R_PPC_DTPREL16_LO; break;
case BFD_RELOC_PPC_DTPREL16_HI: r = R_PPC_DTPREL16_HI; break;
case BFD_RELOC_PPC_DTPREL16_HA: r = R_PPC_DTPREL16_HA; break;
@ -7243,6 +7255,21 @@ _bfd_elf_ppc_at_tprel_transform (unsigned int insn, unsigned int reg)
return insn;
}
static bfd_boolean
is_insn_ds_form (unsigned int insn)
{
return ((insn & (0x3f << 26)) == 58u << 26 /* ld,ldu,lwa */
|| (insn & (0x3f << 26)) == 62u << 26 /* std,stdu,stq */
|| (insn & (0x3f << 26)) == 57u << 26 /* lfdp */
|| (insn & (0x3f << 26)) == 61u << 26 /* stfdp */);
}
static bfd_boolean
is_insn_dq_form (unsigned int insn)
{
return (insn & (0x3f << 26)) == 56u << 26; /* lq */
}
/* The RELOCATE_SECTION function is called by the ELF backend linker
to handle the relocations for a section.
@ -8788,6 +8815,54 @@ ppc_elf_relocate_section (bfd *output_bfd,
Bits 0:15 are not used. */
addend += 0x8000;
break;
case R_PPC_ADDR16:
case R_PPC_ADDR16_LO:
case R_PPC_GOT16:
case R_PPC_GOT16_LO:
case R_PPC_SDAREL16:
case R_PPC_SECTOFF:
case R_PPC_SECTOFF_LO:
case R_PPC_DTPREL16:
case R_PPC_DTPREL16_LO:
case R_PPC_TPREL16:
case R_PPC_TPREL16_LO:
case R_PPC_GOT_TLSGD16:
case R_PPC_GOT_TLSGD16_LO:
case R_PPC_GOT_TLSLD16:
case R_PPC_GOT_TLSLD16_LO:
case R_PPC_GOT_DTPREL16:
case R_PPC_GOT_DTPREL16_LO:
case R_PPC_GOT_TPREL16:
case R_PPC_GOT_TPREL16_LO:
{
/* The 32-bit ABI lacks proper relocations to deal with
certain 64-bit instructions. Prevent damage to bits
that make up part of the insn opcode. */
unsigned int insn, mask, lobit;
insn = bfd_get_32 (output_bfd, contents + rel->r_offset - d_offset);
mask = 0;
if (is_insn_ds_form (insn))
mask = 3;
else if (is_insn_dq_form (insn))
mask = 15;
else
break;
lobit = mask & (relocation + addend);
if (lobit != 0)
{
addend -= lobit;
info->callbacks->einfo
(_("%P: %H: error: %s against `%s' not a multiple of %u\n"),
input_bfd, input_section, rel->r_offset,
howto->name, sym_name, mask + 1);
bfd_set_error (bfd_error_bad_value);
ret = FALSE;
}
addend += insn & mask;
}
break;
}
#ifdef DEBUG

View file

@ -1,3 +1,10 @@
2012-10-26 Alan Modra <amodra@gmail.com>
PR target/14758
* config/tc-ppc.c (ppc_setup_opcodes): Fix comment.
(md_assemble): Translate to _DS relocs for ppc32 as well as ppc64.
(tc_gen_reloc): Handle _DS relocs in ppc32 mode.
2012-10-22 Simon Baldwin <simonb@google.com>
* as.c (dump_statistics): Compute data size as the delta between

View file

@ -1513,7 +1513,7 @@ insn_validate (const struct powerpc_opcode *op)
}
/* Insert opcodes and macros into hash tables. Called at startup and
for .cpu pseudo. */
for .machine pseudo. */
static void
ppc_setup_opcodes (void)
@ -3062,8 +3062,7 @@ md_assemble (char *str)
break;
}
if (ppc_obj64
&& (operand->flags & (PPC_OPERAND_DS | PPC_OPERAND_DQ)) != 0)
if ((operand->flags & (PPC_OPERAND_DS | PPC_OPERAND_DQ)) != 0)
{
switch (reloc)
{