This is the mail archive of the binutils-cvs@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb/binutils-2_25-branch] ppc476 linker workaround shared lib fixes


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=2bc6144cb70a4bd4129d12afe3313a20235fc31e

commit 2bc6144cb70a4bd4129d12afe3313a20235fc31e
Author: Alan Modra <amodra@gmail.com>
Date:   Fri Jun 5 18:35:40 2015 +0930

    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.

Diff:
---
 bfd/ChangeLog                             |  5 +++
 bfd/elf32-ppc.c                           | 52 +++++++++++++++++++++++++++++++
 ld/testsuite/ChangeLog                    |  7 +++++
 ld/testsuite/ld-powerpc/powerpc.exp       |  3 ++
 ld/testsuite/ld-powerpc/ppc476-shared.d   | 30 ++++++++++++++++++
 ld/testsuite/ld-powerpc/ppc476-shared.lnk |  6 ++++
 ld/testsuite/ld-powerpc/ppc476-shared.s   | 13 ++++++++
 ld/testsuite/ld-powerpc/ppc476-shared2.d  | 12 +++++++
 8 files changed, 128 insertions(+)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 0893d39..ab2bb50 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,6 +1,11 @@
 2015-07-10  Alan Modra  <amodra@gmail.com>
 
 	Apply from master
+	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-04-23  Alan Modra  <amodra@gmail.com>
 	* elf64-ppc.c (TOC_BASE_ALIGN): Define.
 	(ppc64_elf_next_toc_section): Align multi-got toc base.
diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index d0559d1..ed19972 100644
--- a/bfd/elf32-ppc.c
+++ b/bfd/elf32-ppc.c
@@ -9428,6 +9428,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.  */
@@ -9440,6 +9442,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;
diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog
index c0be981..7e9895d 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -1,6 +1,13 @@
 2015-07-10  Alan Modra  <amodra@gmail.com>
 
 	Apply from master
+	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-04-23  Alan Modra  <amodra@gmail.com>
 	* ld-powerpc/ambiguousv1.d: Update for aligned .got.
 	* ld-powerpc/ambiguousv1b.d: Likewise.
diff --git a/ld/testsuite/ld-powerpc/powerpc.exp b/ld/testsuite/ld-powerpc/powerpc.exp
index 8fc261e..239aa91 100644
--- a/ld/testsuite/ld-powerpc/powerpc.exp
+++ b/ld/testsuite/ld-powerpc/powerpc.exp
@@ -323,3 +323,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"
diff --git a/ld/testsuite/ld-powerpc/ppc476-shared.d b/ld/testsuite/ld-powerpc/ppc476-shared.d
new file mode 100644
index 0000000..8fda847
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/ppc476-shared.d
@@ -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 .*
diff --git a/ld/testsuite/ld-powerpc/ppc476-shared.lnk b/ld/testsuite/ld-powerpc/ppc476-shared.lnk
new file mode 100644
index 0000000..5339358
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/ppc476-shared.lnk
@@ -0,0 +1,6 @@
+SECTIONS
+{
+  . = 0xfffc;
+  .text : { *(.text) }
+  .bss : { *(.bss) }
+}
diff --git a/ld/testsuite/ld-powerpc/ppc476-shared.s b/ld/testsuite/ld-powerpc/ppc476-shared.s
new file mode 100644
index 0000000..6774bad
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/ppc476-shared.s
@@ -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
diff --git a/ld/testsuite/ld-powerpc/ppc476-shared2.d b/ld/testsuite/ld-powerpc/ppc476-shared2.d
new file mode 100644
index 0000000..ebb8bf1
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/ppc476-shared2.d
@@ -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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]