ppc476 linker workaround shared lib fixes

When building a shared lib from non-PIC objects, we'll get dynamic
text relocations.  These need to move with any insns we move.
Otherwise the dynamic reloc will modify the branch, resulting in
crashes and other unpleasant behaviour.

Also, ld -r --ppc476-workaround used with sufficiently aligned PIC
objects needs a fix for emitted REL16 relocs.

bfd/
	* elf64-ppc.c (ppc_elf_relocate_section): Move dynamic text
	relocs with insns moved by --ppc476-workaround.  Correct
	output of REL16 relocs.
ld/testsuite/
	* ld-powerpc/ppc476-shared.s,
	* ld-powerpc/ppc476-shared.lnk,
	* ld-powerpc/ppc476-shared.d,
	* ld-powerpc/ppc476-shared2.d: New tests.
	* ld-powerpc/powerpc.exp: Run them.
This commit is contained in:
Alan Modra 2015-06-05 18:35:40 +09:30
parent bdd2d2b7e6
commit f8b447819b
8 changed files with 130 additions and 0 deletions

View File

@ -1,3 +1,9 @@
2015-06-05 Alan Modra <amodra@gmail.com>
* elf64-ppc.c (ppc_elf_relocate_section): Move dynamic text
relocs with insns moved by --ppc476-workaround. Correct
output of REL16 relocs.
2015-06-01 Jiong Wang <jiong.wang@arm.com>
* elfnn-aarch64.c (aarch64_reloc_got_type): Support

View File

@ -9608,6 +9608,8 @@ ppc_elf_relocate_section (bfd *output_bfd,
&& rel->r_offset >= offset
&& rel->r_offset < offset + 4)
{
asection *sreloc;
/* If the insn we are patching had a reloc, adjust the
reloc r_offset so that the reloc applies to the moved
location. This matters for -r and --emit-relocs. */
@ -9620,6 +9622,56 @@ ppc_elf_relocate_section (bfd *output_bfd,
relend[-1] = tmp;
}
relend[-1].r_offset += patch_off - offset;
/* Adjust REL16 addends too. */
switch (ELF32_R_TYPE (relend[-1].r_info))
{
case R_PPC_REL16:
case R_PPC_REL16_LO:
case R_PPC_REL16_HI:
case R_PPC_REL16_HA:
relend[-1].r_addend += patch_off - offset;
break;
default:
break;
}
/* If we are building a PIE or shared library with
non-PIC objects, perhaps we had a dynamic reloc too?
If so, the dynamic reloc must move with the insn. */
sreloc = elf_section_data (input_section)->sreloc;
if (sreloc != NULL)
{
bfd_byte *slo, *shi, *srelend;
bfd_vma soffset;
slo = sreloc->contents;
shi = srelend
= slo + sreloc->reloc_count * sizeof (Elf32_External_Rela);
soffset = (offset + input_section->output_section->vma
+ input_section->output_offset);
while (slo < shi)
{
bfd_byte *srel = slo + (shi - slo) / 2;
bfd_elf32_swap_reloca_in (output_bfd, srel, &outrel);
if (outrel.r_offset < soffset)
slo = srel + 1;
else if (outrel.r_offset > soffset + 3)
shi = srel;
else
{
bfd_byte *nextr = srel + sizeof (Elf32_External_Rela);
if (nextr != srelend)
{
memmove (srel, nextr, srelend - nextr);
srel = srelend - sizeof (Elf32_External_Rela);
}
outrel.r_offset += patch_off - offset;
bfd_elf32_swap_reloca_out (output_bfd, &outrel, srel);
break;
}
}
}
}
else
rel = NULL;

View File

@ -1,3 +1,11 @@
2015-06-05 Alan Modra <amodra@gmail.com>
* ld-powerpc/ppc476-shared.s,
* ld-powerpc/ppc476-shared.lnk,
* ld-powerpc/ppc476-shared.d,
* ld-powerpc/ppc476-shared2.d: New tests.
* ld-powerpc/powerpc.exp: Run them.
2015-06-02 Jiong Wang <jiong.wang@arm.com>
* ld-aarch64/emit-relocs-313.s: Use gotpage_lo15.

View File

@ -325,3 +325,6 @@ run_dump_test "attr-gnu-12-11"
run_dump_test "attr-gnu-12-21"
run_dump_test "vle-multiseg-6"
run_dump_test "ppc476-shared"
run_dump_test "ppc476-shared2"

View File

@ -0,0 +1,30 @@
#source: ppc476-shared.s
#as: -a32
#ld: -melf32ppc -q -shared --ppc476-workaround -T ppc476-shared.lnk
#objdump: -dr
#target: powerpc*-*-*
.*: file format .*
Disassembly of section \.text:
0+fffc <\.text>:
fffc: (48 01 00 04|04 00 01 48) b 20000 .*
10000: (38 63 00 00|00 00 63 38) addi r3,r3,0
1000[02]: R_PPC_ADDR16_LO .bss
\.\.\.
1fff0: (42 9f 00 05|05 00 9f 42) bcl .*
1fff4: (7d 28 02 a6|a6 02 28 7d) mflr r9
1fff8: (3d 29 00 00|00 00 29 3d) addis r9,r9,0
1fff[8a]: R_PPC_REL16_HA .bss\+0x[46]
1fffc: (48 00 00 14|14 00 00 48) b 20010 .*
20000: (3c 60 00 00|00 00 60 3c) lis r3,0
2000[02]: R_PPC_ADDR16_HA .bss
20004: (4b fe ff fc|fc ff fe 4b) b 10000 .*
20008: (48 00 00 02|02 00 00 48) ba 0 .*
2000c: (48 00 00 02|02 00 00 48) ba 0 .*
20010: (39 29 01 00|00 01 29 39) addi r9,r9,256
2001[02]: R_PPC_REL16_LO .bss\+0x1[ce]
20014: (4b ff ff ec|ec ff ff 4b) b 20000 .*
20018: (48 00 00 02|02 00 00 48) ba 0 .*
2001c: (48 00 00 02|02 00 00 48) ba 0 .*

View File

@ -0,0 +1,6 @@
SECTIONS
{
. = 0xfffc;
.text : { *(.text) }
.bss : { *(.bss) }
}

View File

@ -0,0 +1,13 @@
.text
lis 3,x@ha
addi 3,3,x@l
.org 0xfff4
bcl 20,31,.+4
0:
mflr 9
addis 9,9,x-0b@ha
addi 9,9,x-0b@l
.section .bss,"aw",@nobits
x: .space 4

View File

@ -0,0 +1,12 @@
#source: ppc476-shared.s
#as: -a32
#ld: -melf32ppc -shared --ppc476-workaround -T ppc476-shared.lnk
#objdump: -R
#target: powerpc*-*-*
.*: file format .*
DYNAMIC RELOCATION RECORDS
OFFSET TYPE VALUE
0001000[02] R_PPC_ADDR16_LO \.text\+0x000200f4
0002000[02] R_PPC_ADDR16_HA \.text\+0x000200f4