Skip to content

Commit 08dc996

Browse files
committed
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.
1 parent 95f0d0d commit 08dc996

12 files changed

Lines changed: 257 additions & 135 deletions

File tree

‎bfd/ChangeLog‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
2016-11-22 Alan Modra <amodra@gmail.com>
2+
3+
PR 20744
4+
* elf32-ppc.h (struct ppc_elf_params): Add vle_reloc_fixup field.
5+
* elf32-ppc.c: Include opcode/ppc.h.
6+
(ppc_elf_howto_raw): Correct dst_mask for R_PPC_VLE_LO16A,
7+
R_PPC_VLE_LO16D, R_PPC_VLE_HI16A, R_PPC_VLE_HI16D, R_PPC_VLE_HA16A,
8+
R_PPC_VLE_HA16D, R_PPC_VLE_SDAREL_LO16A, R_PPC_VLE_SDAREL_LO16D,
9+
R_PPC_VLE_SDAREL_HI16A, R_PPC_VLE_SDAREL_HI16D,
10+
R_PPC_VLE_SDAREL_HA16A, and R_PPC_VLE_SDAREL_HA16D relocs.
11+
(ppc_elf_link_hash_table_create): Update default_params init.
12+
(ppc_elf_vle_split16): Correct shift and mask. Add params.
13+
Report or fix insn/reloc mismatches.
14+
(ppc_elf_relocate_section): Pass input_section, offset and fixup
15+
to ppc_elf_vle_split16.
16+
117
2016-11-22 Alan Modra <amodra@gmail.com>
218

319
* elf32-ppc.c (ppc64_elf_relocate_section): Calculate d_offset for

‎bfd/elf32-ppc.c‎

Lines changed: 100 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "elf32-ppc.h"
3636
#include "elf-vxworks.h"
3737
#include "dwarf2.h"
38+
#include "opcode/ppc.h"
3839

3940
typedef enum split16_format_type
4041
{
@@ -1455,7 +1456,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
14551456
"R_PPC_VLE_LO16A", /* name */
14561457
FALSE, /* partial_inplace */
14571458
0, /* src_mask */
1458-
0x1f007ff, /* dst_mask */
1459+
0x1f07ff, /* dst_mask */
14591460
FALSE), /* pcrel_offset */
14601461

14611462
/* The 16 LSBS in split16d format. */
@@ -1470,7 +1471,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
14701471
"R_PPC_VLE_LO16D", /* name */
14711472
FALSE, /* partial_inplace */
14721473
0, /* src_mask */
1473-
0x1f07ff, /* dst_mask */
1474+
0x1f007ff, /* dst_mask */
14741475
FALSE), /* pcrel_offset */
14751476

14761477
/* Bits 16-31 split16a format. */
@@ -1485,7 +1486,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
14851486
"R_PPC_VLE_HI16A", /* name */
14861487
FALSE, /* partial_inplace */
14871488
0, /* src_mask */
1488-
0x1f007ff, /* dst_mask */
1489+
0x1f07ff, /* dst_mask */
14891490
FALSE), /* pcrel_offset */
14901491

14911492
/* Bits 16-31 split16d format. */
@@ -1500,7 +1501,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
15001501
"R_PPC_VLE_HI16D", /* name */
15011502
FALSE, /* partial_inplace */
15021503
0, /* src_mask */
1503-
0x1f07ff, /* dst_mask */
1504+
0x1f007ff, /* dst_mask */
15041505
FALSE), /* pcrel_offset */
15051506

15061507
/* Bits 16-31 (High Adjusted) in split16a format. */
@@ -1515,7 +1516,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
15151516
"R_PPC_VLE_HA16A", /* name */
15161517
FALSE, /* partial_inplace */
15171518
0, /* src_mask */
1518-
0x1f007ff, /* dst_mask */
1519+
0x1f07ff, /* dst_mask */
15191520
FALSE), /* pcrel_offset */
15201521

15211522
/* Bits 16-31 (High Adjusted) in split16d format. */
@@ -1530,7 +1531,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
15301531
"R_PPC_VLE_HA16D", /* name */
15311532
FALSE, /* partial_inplace */
15321533
0, /* src_mask */
1533-
0x1f07ff, /* dst_mask */
1534+
0x1f007ff, /* dst_mask */
15341535
FALSE), /* pcrel_offset */
15351536

15361537
/* 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[] = {
15771578
"R_PPC_VLE_SDAREL_LO16A", /* name */
15781579
FALSE, /* partial_inplace */
15791580
0, /* src_mask */
1580-
0x1f007ff, /* dst_mask */
1581+
0x1f07ff, /* dst_mask */
15811582
FALSE), /* pcrel_offset */
15821583

15831584
/* The 16 LSBS relative to _SDA_BASE_ in split16d format. */
@@ -1592,7 +1593,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
15921593
"R_PPC_VLE_SDAREL_LO16D", /* name */
15931594
FALSE, /* partial_inplace */
15941595
0, /* src_mask */
1595-
0x1f07ff, /* dst_mask */
1596+
0x1f007ff, /* dst_mask */
15961597
FALSE), /* pcrel_offset */
15971598

15981599
/* Bits 16-31 relative to _SDA_BASE_ in split16a format. */
@@ -1607,7 +1608,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
16071608
"R_PPC_VLE_SDAREL_HI16A", /* name */
16081609
FALSE, /* partial_inplace */
16091610
0, /* src_mask */
1610-
0x1f007ff, /* dst_mask */
1611+
0x1f07ff, /* dst_mask */
16111612
FALSE), /* pcrel_offset */
16121613

16131614
/* Bits 16-31 relative to _SDA_BASE_ in split16d format. */
@@ -1622,7 +1623,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
16221623
"R_PPC_VLE_SDAREL_HI16D", /* name */
16231624
FALSE, /* partial_inplace */
16241625
0, /* src_mask */
1625-
0x1f07ff, /* dst_mask */
1626+
0x1f007ff, /* dst_mask */
16261627
FALSE), /* pcrel_offset */
16271628

16281629
/* Bits 16-31 (HA) relative to _SDA_BASE split16a format. */
@@ -1637,7 +1638,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
16371638
"R_PPC_VLE_SDAREL_HA16A", /* name */
16381639
FALSE, /* partial_inplace */
16391640
0, /* src_mask */
1640-
0x1f007ff, /* dst_mask */
1641+
0x1f07ff, /* dst_mask */
16411642
FALSE), /* pcrel_offset */
16421643

16431644
/* Bits 16-31 (HA) relative to _SDA_BASE split16d format. */
@@ -1652,7 +1653,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
16521653
"R_PPC_VLE_SDAREL_HA16D", /* name */
16531654
FALSE, /* partial_inplace */
16541655
0, /* src_mask */
1655-
0x1f07ff, /* dst_mask */
1656+
0x1f007ff, /* dst_mask */
16561657
FALSE), /* pcrel_offset */
16571658

16581659
HOWTO (R_PPC_IRELATIVE, /* type */
@@ -3384,7 +3385,7 @@ ppc_elf_link_hash_table_create (bfd *abfd)
33843385
{
33853386
struct ppc_elf_link_hash_table *ret;
33863387
static struct ppc_elf_params default_params
3387-
= { PLT_OLD, 0, 1, 0, 0, 12, 0, 0 };
3388+
= { PLT_OLD, 0, 1, 0, 0, 12, 0, 0, 0 };
33883389

33893390
ret = bfd_zmalloc (sizeof (struct ppc_elf_link_hash_table));
33903391
if (ret == NULL)
@@ -4925,16 +4926,56 @@ ppc_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
49254926

49264927
static void
49274928
ppc_elf_vle_split16 (bfd *input_bfd,
4929+
asection *input_section,
4930+
unsigned long offset,
49284931
bfd_byte *loc,
49294932
bfd_vma value,
4930-
split16_format_type split16_format)
4933+
split16_format_type split16_format,
4934+
bfd_boolean fixup)
49314935
{
4932-
unsigned int insn, top5;
4936+
unsigned int insn, opcode, top5;
49334937

49344938
insn = bfd_get_32 (input_bfd, loc);
4939+
opcode = insn & 0xf300f800;
4940+
if (opcode == E_OR2I_INSN
4941+
|| opcode == E_AND2I_DOT_INSN
4942+
|| opcode == E_OR2IS_INSN
4943+
|| opcode == E_LIS_INSN
4944+
|| opcode == E_AND2IS_DOT_INSN)
4945+
{
4946+
if (split16_format != split16a_type)
4947+
{
4948+
if (fixup)
4949+
split16_format = split16a_type;
4950+
else
4951+
_bfd_error_handler
4952+
/* xgettext:c-format */
4953+
(_("%B(%A+0x%lx): expected 16A style relocation on 0x%08x insn"),
4954+
input_bfd, input_section, offset, opcode);
4955+
}
4956+
}
4957+
else if (opcode == E_ADD2I_DOT_INSN
4958+
|| opcode == E_ADD2IS_INSN
4959+
|| opcode == E_CMP16I_INSN
4960+
|| opcode == E_MULL2I_INSN
4961+
|| opcode == E_CMPL16I_INSN
4962+
|| opcode == E_CMPH16I_INSN
4963+
|| opcode == E_CMPHL16I_INSN)
4964+
{
4965+
if (split16_format != split16d_type)
4966+
{
4967+
if (fixup)
4968+
split16_format = split16d_type;
4969+
else
4970+
_bfd_error_handler
4971+
/* xgettext:c-format */
4972+
(_("%B(%A+0x%lx): expected 16D style relocation on 0x%08x insn"),
4973+
input_bfd, input_section, offset, opcode);
4974+
}
4975+
}
49354976
top5 = value & 0xf800;
4936-
top5 = top5 << (split16_format == split16a_type ? 9 : 5);
4937-
insn &= (split16_format == split16a_type ? ~0x1f007ff : ~0x1f07ff);
4977+
top5 = top5 << (split16_format == split16a_type ? 5 : 9);
4978+
insn &= (split16_format == split16a_type ? ~0x1f07ff : ~0x1f007ff);
49384979
insn |= top5;
49394980
insn |= value & 0x7ff;
49404981
bfd_put_32 (input_bfd, insn, loc);
@@ -9220,38 +9261,44 @@ ppc_elf_relocate_section (bfd *output_bfd,
92209261

92219262
case R_PPC_VLE_LO16A:
92229263
relocation = relocation + addend;
9223-
ppc_elf_vle_split16 (input_bfd, contents + rel->r_offset,
9224-
relocation, split16a_type);
9264+
ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
9265+
contents + rel->r_offset, relocation,
9266+
split16a_type, htab->params->vle_reloc_fixup);
92259267
goto copy_reloc;
92269268

92279269
case R_PPC_VLE_LO16D:
92289270
relocation = relocation + addend;
9229-
ppc_elf_vle_split16 (input_bfd, contents + rel->r_offset,
9230-
relocation, split16d_type);
9271+
ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
9272+
contents + rel->r_offset, relocation,
9273+
split16d_type, htab->params->vle_reloc_fixup);
92319274
goto copy_reloc;
92329275

92339276
case R_PPC_VLE_HI16A:
92349277
relocation = (relocation + addend) >> 16;
9235-
ppc_elf_vle_split16 (input_bfd, contents + rel->r_offset,
9236-
relocation, split16a_type);
9278+
ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
9279+
contents + rel->r_offset, relocation,
9280+
split16a_type, htab->params->vle_reloc_fixup);
92379281
goto copy_reloc;
92389282

92399283
case R_PPC_VLE_HI16D:
92409284
relocation = (relocation + addend) >> 16;
9241-
ppc_elf_vle_split16 (input_bfd, contents + rel->r_offset,
9242-
relocation, split16d_type);
9285+
ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
9286+
contents + rel->r_offset, relocation,
9287+
split16d_type, htab->params->vle_reloc_fixup);
92439288
goto copy_reloc;
92449289

92459290
case R_PPC_VLE_HA16A:
92469291
relocation = (relocation + addend + 0x8000) >> 16;
9247-
ppc_elf_vle_split16 (input_bfd, contents + rel->r_offset,
9248-
relocation, split16a_type);
9292+
ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
9293+
contents + rel->r_offset, relocation,
9294+
split16a_type, htab->params->vle_reloc_fixup);
92499295
goto copy_reloc;
92509296

92519297
case R_PPC_VLE_HA16D:
92529298
relocation = (relocation + addend + 0x8000) >> 16;
9253-
ppc_elf_vle_split16 (input_bfd, contents + rel->r_offset,
9254-
relocation, split16d_type);
9299+
ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
9300+
contents + rel->r_offset, relocation,
9301+
split16d_type, htab->params->vle_reloc_fixup);
92559302
goto copy_reloc;
92569303

92579304
/* Relocate against either _SDA_BASE_, _SDA2_BASE_, or 0. */
@@ -9414,34 +9461,46 @@ ppc_elf_relocate_section (bfd *output_bfd,
94149461
+ addend);
94159462

94169463
if (r_type == R_PPC_VLE_SDAREL_LO16A)
9417-
ppc_elf_vle_split16 (input_bfd, contents + rel->r_offset,
9418-
value, split16a_type);
9464+
ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
9465+
contents + rel->r_offset, value,
9466+
split16a_type,
9467+
htab->params->vle_reloc_fixup);
94199468
else if (r_type == R_PPC_VLE_SDAREL_LO16D)
9420-
ppc_elf_vle_split16 (input_bfd, contents + rel->r_offset,
9421-
value, split16d_type);
9469+
ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
9470+
contents + rel->r_offset, value,
9471+
split16d_type,
9472+
htab->params->vle_reloc_fixup);
94229473
else if (r_type == R_PPC_VLE_SDAREL_HI16A)
94239474
{
94249475
value = value >> 16;
9425-
ppc_elf_vle_split16 (input_bfd, contents + rel->r_offset,
9426-
value, split16a_type);
9476+
ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
9477+
contents + rel->r_offset, value,
9478+
split16a_type,
9479+
htab->params->vle_reloc_fixup);
94279480
}
94289481
else if (r_type == R_PPC_VLE_SDAREL_HI16D)
94299482
{
94309483
value = value >> 16;
9431-
ppc_elf_vle_split16 (input_bfd, contents + rel->r_offset,
9432-
value, split16d_type);
9484+
ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
9485+
contents + rel->r_offset, value,
9486+
split16d_type,
9487+
htab->params->vle_reloc_fixup);
94339488
}
94349489
else if (r_type == R_PPC_VLE_SDAREL_HA16A)
94359490
{
94369491
value = (value + 0x8000) >> 16;
9437-
ppc_elf_vle_split16 (input_bfd, contents + rel->r_offset,
9438-
value, split16a_type);
9492+
ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
9493+
contents + rel->r_offset, value,
9494+
split16a_type,
9495+
htab->params->vle_reloc_fixup);
94399496
}
94409497
else if (r_type == R_PPC_VLE_SDAREL_HA16D)
94419498
{
94429499
value = (value + 0x8000) >> 16;
9443-
ppc_elf_vle_split16 (input_bfd, contents + rel->r_offset,
9444-
value, split16d_type);
9500+
ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
9501+
contents + rel->r_offset, value,
9502+
split16d_type,
9503+
htab->params->vle_reloc_fixup);
94459504
}
94469505
}
94479506
goto copy_reloc;

‎bfd/elf32-ppc.h‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ struct ppc_elf_params
4949
defined in a shared library. */
5050
int pic_fixup;
5151

52+
/* Relocate 16A relocs as 16D and vice versa. */
53+
int vle_reloc_fixup;
54+
5255
bfd_vma pagesize;
5356
};
5457

‎binutils/ChangeLog‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
2016-11-22 Alan Modra <amodra@gmail.com>
2+
3+
PR 20744
4+
* NEWS: Mention PowerPC VLE relocation error.
5+
16
2016-11-16 Mark Wielaard <mark@klomp.org>
27

38
* cxxfilt.c (main): Recognize rust_demangling.

‎binutils/NEWS‎

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,19 @@
11
-*- text -*-
22

3-
* The nm program has a new command lien option (--with-version-strings)
3+
* This version of binutils fixes a problem with PowerPC VLE 16A and 16D
4+
relocations which were functionally swapped, for example,
5+
R_PPC_VLE_HA16A performed like R_PPC_VLE_HA16D while R_PPC_VLE_HA16D
6+
performed like R_PPC_VLE_HA16A. This could have been fixed by
7+
renumbering relocations, which would keep object files created by an
8+
older version of gas compatible with a newer ld. However, that would
9+
require an ABI update, affecting other assemblers and linkers that
10+
create and process the relocations correctly. It is recommended that
11+
all VLE object files be recompiled, but ld can modify the relocations
12+
if --vle-reloc-fixup is passed to ld. If the new ld command line
13+
option is not used, ld will ld warn on finding relocations inconsistent
14+
with the instructions being relocated.
15+
16+
* The nm program has a new command line option (--with-version-strings)
417
which will display a symbol's version information, if any, after the
518
symbol's name.
619

‎gas/ChangeLog‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
2016-11-22 Alan Modra <amodra@gmail.com>
2+
3+
PR 20744
4+
* config/tc-ppc.c: Delete VLE insn defines.
5+
(md_assemble): Swap use_a_reloc and use_d_reloc.
6+
* testsuite/gas/ppc/vle-reloc.d: Update.
7+
18
2016-11-21 Renlin Li <renlin.li@arm.com>
29

310
PR gas/20827

0 commit comments

Comments
 (0)