diff options
author | Alan Modra <amodra@gmail.com> | 2016-11-22 18:45:29 +1030 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2016-11-22 20:19:29 +1030 |
commit | 08dc996fedde9143cda25720961684087b133640 (patch) | |
tree | 9bb48db13193c8e0839bc213eb2fc9ca8a73adb8 /bfd | |
parent | Use input_bfd in relocate_section (diff) | |
download | binutils-gdb-08dc996fedde9143cda25720961684087b133640.tar.gz binutils-gdb-08dc996fedde9143cda25720961684087b133640.tar.bz2 binutils-gdb-08dc996fedde9143cda25720961684087b133640.zip |
PR20744, Incorrect PowerPC VLE relocs
VLE 16A and 16D relocs were functionally swapped.
PR 20744
include/
* opcode/ppc.h: Define VLE insns using 16A and 16D relocs.
bfd/
* elf32-ppc.h (struct ppc_elf_params): Add vle_reloc_fixup field.
* elf32-ppc.c: Include opcode/ppc.h.
(ppc_elf_howto_raw): Correct dst_mask for R_PPC_VLE_LO16A,
R_PPC_VLE_LO16D, R_PPC_VLE_HI16A, R_PPC_VLE_HI16D, R_PPC_VLE_HA16A,
R_PPC_VLE_HA16D, R_PPC_VLE_SDAREL_LO16A, R_PPC_VLE_SDAREL_LO16D,
R_PPC_VLE_SDAREL_HI16A, R_PPC_VLE_SDAREL_HI16D,
R_PPC_VLE_SDAREL_HA16A, and R_PPC_VLE_SDAREL_HA16D relocs.
(ppc_elf_link_hash_table_create): Update default_params init.
(ppc_elf_vle_split16): Correct shift and mask. Add params.
Report or fix insn/reloc mismatches.
(ppc_elf_relocate_section): Pass input_section, offset and fixup
to ppc_elf_vle_split16.
binutils/
* NEWS: Mention PowerPC VLE relocation error.
gas/
* config/tc-ppc.c: Delete VLE insn defines.
(md_assemble): Swap use_a_reloc and use_d_reloc.
* testsuite/gas/ppc/vle-reloc.d: Update.
ld/
* emultempl/ppc32elf.em (params): Update initializer. Handle
--vle-reloc-fixup command line arg.
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/ChangeLog | 16 | ||||
-rw-r--r-- | bfd/elf32-ppc.c | 141 | ||||
-rw-r--r-- | bfd/elf32-ppc.h | 3 |
3 files changed, 119 insertions, 41 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index c3283ea7ebc..ebf82794802 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,5 +1,21 @@ 2016-11-22 Alan Modra <amodra@gmail.com> + PR 20744 + * elf32-ppc.h (struct ppc_elf_params): Add vle_reloc_fixup field. + * elf32-ppc.c: Include opcode/ppc.h. + (ppc_elf_howto_raw): Correct dst_mask for R_PPC_VLE_LO16A, + R_PPC_VLE_LO16D, R_PPC_VLE_HI16A, R_PPC_VLE_HI16D, R_PPC_VLE_HA16A, + R_PPC_VLE_HA16D, R_PPC_VLE_SDAREL_LO16A, R_PPC_VLE_SDAREL_LO16D, + R_PPC_VLE_SDAREL_HI16A, R_PPC_VLE_SDAREL_HI16D, + R_PPC_VLE_SDAREL_HA16A, and R_PPC_VLE_SDAREL_HA16D relocs. + (ppc_elf_link_hash_table_create): Update default_params init. + (ppc_elf_vle_split16): Correct shift and mask. Add params. + Report or fix insn/reloc mismatches. + (ppc_elf_relocate_section): Pass input_section, offset and fixup + to ppc_elf_vle_split16. + +2016-11-22 Alan Modra <amodra@gmail.com> + * elf32-ppc.c (ppc64_elf_relocate_section): Calculate d_offset for input_bfd. Replace occurrences of output_bfd as bfd_get_32 and bfd_put_32 param with input_bfd. diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index 75b0478d2b8..efe7f69b83c 100644 --- a/bfd/elf32-ppc.c +++ b/bfd/elf32-ppc.c @@ -35,6 +35,7 @@ #include "elf32-ppc.h" #include "elf-vxworks.h" #include "dwarf2.h" +#include "opcode/ppc.h" typedef enum split16_format_type { @@ -1455,7 +1456,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = { "R_PPC_VLE_LO16A", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ - 0x1f007ff, /* dst_mask */ + 0x1f07ff, /* dst_mask */ FALSE), /* pcrel_offset */ /* The 16 LSBS in split16d format. */ @@ -1470,7 +1471,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = { "R_PPC_VLE_LO16D", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ - 0x1f07ff, /* dst_mask */ + 0x1f007ff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Bits 16-31 split16a format. */ @@ -1485,7 +1486,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = { "R_PPC_VLE_HI16A", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ - 0x1f007ff, /* dst_mask */ + 0x1f07ff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Bits 16-31 split16d format. */ @@ -1500,7 +1501,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = { "R_PPC_VLE_HI16D", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ - 0x1f07ff, /* dst_mask */ + 0x1f007ff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Bits 16-31 (High Adjusted) in split16a format. */ @@ -1515,7 +1516,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = { "R_PPC_VLE_HA16A", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ - 0x1f007ff, /* dst_mask */ + 0x1f07ff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Bits 16-31 (High Adjusted) in split16d format. */ @@ -1530,7 +1531,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = { "R_PPC_VLE_HA16D", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ - 0x1f07ff, /* dst_mask */ + 0x1f007ff, /* dst_mask */ FALSE), /* pcrel_offset */ /* This reloc is like R_PPC_EMB_SDA21 but only applies to e_add16i @@ -1577,7 +1578,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = { "R_PPC_VLE_SDAREL_LO16A", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ - 0x1f007ff, /* dst_mask */ + 0x1f07ff, /* dst_mask */ FALSE), /* pcrel_offset */ /* The 16 LSBS relative to _SDA_BASE_ in split16d format. */ @@ -1592,7 +1593,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = { "R_PPC_VLE_SDAREL_LO16D", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ - 0x1f07ff, /* dst_mask */ + 0x1f007ff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Bits 16-31 relative to _SDA_BASE_ in split16a format. */ @@ -1607,7 +1608,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = { "R_PPC_VLE_SDAREL_HI16A", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ - 0x1f007ff, /* dst_mask */ + 0x1f07ff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Bits 16-31 relative to _SDA_BASE_ in split16d format. */ @@ -1622,7 +1623,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = { "R_PPC_VLE_SDAREL_HI16D", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ - 0x1f07ff, /* dst_mask */ + 0x1f007ff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Bits 16-31 (HA) relative to _SDA_BASE split16a format. */ @@ -1637,7 +1638,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = { "R_PPC_VLE_SDAREL_HA16A", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ - 0x1f007ff, /* dst_mask */ + 0x1f07ff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Bits 16-31 (HA) relative to _SDA_BASE split16d format. */ @@ -1652,7 +1653,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = { "R_PPC_VLE_SDAREL_HA16D", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ - 0x1f07ff, /* dst_mask */ + 0x1f007ff, /* dst_mask */ FALSE), /* pcrel_offset */ HOWTO (R_PPC_IRELATIVE, /* type */ @@ -3384,7 +3385,7 @@ ppc_elf_link_hash_table_create (bfd *abfd) { struct ppc_elf_link_hash_table *ret; static struct ppc_elf_params default_params - = { PLT_OLD, 0, 1, 0, 0, 12, 0, 0 }; + = { PLT_OLD, 0, 1, 0, 0, 12, 0, 0, 0 }; ret = bfd_zmalloc (sizeof (struct ppc_elf_link_hash_table)); if (ret == NULL) @@ -4925,16 +4926,56 @@ ppc_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) static void ppc_elf_vle_split16 (bfd *input_bfd, + asection *input_section, + unsigned long offset, bfd_byte *loc, bfd_vma value, - split16_format_type split16_format) + split16_format_type split16_format, + bfd_boolean fixup) { - unsigned int insn, top5; + unsigned int insn, opcode, top5; insn = bfd_get_32 (input_bfd, loc); + opcode = insn & 0xf300f800; + if (opcode == E_OR2I_INSN + || opcode == E_AND2I_DOT_INSN + || opcode == E_OR2IS_INSN + || opcode == E_LIS_INSN + || opcode == E_AND2IS_DOT_INSN) + { + if (split16_format != split16a_type) + { + if (fixup) + split16_format = split16a_type; + else + _bfd_error_handler + /* xgettext:c-format */ + (_("%B(%A+0x%lx): expected 16A style relocation on 0x%08x insn"), + input_bfd, input_section, offset, opcode); + } + } + else if (opcode == E_ADD2I_DOT_INSN + || opcode == E_ADD2IS_INSN + || opcode == E_CMP16I_INSN + || opcode == E_MULL2I_INSN + || opcode == E_CMPL16I_INSN + || opcode == E_CMPH16I_INSN + || opcode == E_CMPHL16I_INSN) + { + if (split16_format != split16d_type) + { + if (fixup) + split16_format = split16d_type; + else + _bfd_error_handler + /* xgettext:c-format */ + (_("%B(%A+0x%lx): expected 16D style relocation on 0x%08x insn"), + input_bfd, input_section, offset, opcode); + } + } top5 = value & 0xf800; - top5 = top5 << (split16_format == split16a_type ? 9 : 5); - insn &= (split16_format == split16a_type ? ~0x1f007ff : ~0x1f07ff); + top5 = top5 << (split16_format == split16a_type ? 5 : 9); + insn &= (split16_format == split16a_type ? ~0x1f07ff : ~0x1f007ff); insn |= top5; insn |= value & 0x7ff; bfd_put_32 (input_bfd, insn, loc); @@ -9220,38 +9261,44 @@ ppc_elf_relocate_section (bfd *output_bfd, case R_PPC_VLE_LO16A: relocation = relocation + addend; - ppc_elf_vle_split16 (input_bfd, contents + rel->r_offset, - relocation, split16a_type); + ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset, + contents + rel->r_offset, relocation, + split16a_type, htab->params->vle_reloc_fixup); goto copy_reloc; case R_PPC_VLE_LO16D: relocation = relocation + addend; - ppc_elf_vle_split16 (input_bfd, contents + rel->r_offset, - relocation, split16d_type); + ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset, + contents + rel->r_offset, relocation, + split16d_type, htab->params->vle_reloc_fixup); goto copy_reloc; case R_PPC_VLE_HI16A: relocation = (relocation + addend) >> 16; - ppc_elf_vle_split16 (input_bfd, contents + rel->r_offset, - relocation, split16a_type); + ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset, + contents + rel->r_offset, relocation, + split16a_type, htab->params->vle_reloc_fixup); goto copy_reloc; case R_PPC_VLE_HI16D: relocation = (relocation + addend) >> 16; - ppc_elf_vle_split16 (input_bfd, contents + rel->r_offset, - relocation, split16d_type); + ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset, + contents + rel->r_offset, relocation, + split16d_type, htab->params->vle_reloc_fixup); goto copy_reloc; case R_PPC_VLE_HA16A: relocation = (relocation + addend + 0x8000) >> 16; - ppc_elf_vle_split16 (input_bfd, contents + rel->r_offset, - relocation, split16a_type); + ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset, + contents + rel->r_offset, relocation, + split16a_type, htab->params->vle_reloc_fixup); goto copy_reloc; case R_PPC_VLE_HA16D: relocation = (relocation + addend + 0x8000) >> 16; - ppc_elf_vle_split16 (input_bfd, contents + rel->r_offset, - relocation, split16d_type); + ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset, + contents + rel->r_offset, relocation, + split16d_type, htab->params->vle_reloc_fixup); goto copy_reloc; /* Relocate against either _SDA_BASE_, _SDA2_BASE_, or 0. */ @@ -9414,34 +9461,46 @@ ppc_elf_relocate_section (bfd *output_bfd, + addend); if (r_type == R_PPC_VLE_SDAREL_LO16A) - ppc_elf_vle_split16 (input_bfd, contents + rel->r_offset, - value, split16a_type); + ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset, + contents + rel->r_offset, value, + split16a_type, + htab->params->vle_reloc_fixup); else if (r_type == R_PPC_VLE_SDAREL_LO16D) - ppc_elf_vle_split16 (input_bfd, contents + rel->r_offset, - value, split16d_type); + ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset, + contents + rel->r_offset, value, + split16d_type, + htab->params->vle_reloc_fixup); else if (r_type == R_PPC_VLE_SDAREL_HI16A) { value = value >> 16; - ppc_elf_vle_split16 (input_bfd, contents + rel->r_offset, - value, split16a_type); + ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset, + contents + rel->r_offset, value, + split16a_type, + htab->params->vle_reloc_fixup); } else if (r_type == R_PPC_VLE_SDAREL_HI16D) { value = value >> 16; - ppc_elf_vle_split16 (input_bfd, contents + rel->r_offset, - value, split16d_type); + ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset, + contents + rel->r_offset, value, + split16d_type, + htab->params->vle_reloc_fixup); } else if (r_type == R_PPC_VLE_SDAREL_HA16A) { value = (value + 0x8000) >> 16; - ppc_elf_vle_split16 (input_bfd, contents + rel->r_offset, - value, split16a_type); + ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset, + contents + rel->r_offset, value, + split16a_type, + htab->params->vle_reloc_fixup); } else if (r_type == R_PPC_VLE_SDAREL_HA16D) { value = (value + 0x8000) >> 16; - ppc_elf_vle_split16 (input_bfd, contents + rel->r_offset, - value, split16d_type); + ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset, + contents + rel->r_offset, value, + split16d_type, + htab->params->vle_reloc_fixup); } } goto copy_reloc; diff --git a/bfd/elf32-ppc.h b/bfd/elf32-ppc.h index 5f3a88b3d43..0351a2b3a48 100644 --- a/bfd/elf32-ppc.h +++ b/bfd/elf32-ppc.h @@ -49,6 +49,9 @@ struct ppc_elf_params defined in a shared library. */ int pic_fixup; + /* Relocate 16A relocs as 16D and vice versa. */ + int vle_reloc_fixup; + bfd_vma pagesize; }; |