This is the mail archive of the binutils@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]

Enhance powerpc ld -r --relax


GNU ld -r is rarely a good idea but ignorant people persist in using
it, unfortunately.  Maybe they'd learn if ld -r randomly hit an OOM,
or randomly exec'd "sleep 300"?  I'm tempted to insert something like
that rather than making ld -r better.. 

One of the ill effects of ld -r is to mash together sections.  That
can result in reduced icache performance at runtime due to unexpected
movement of code.  Another problem is that sections can become too
large to link on targets that have limited relative addressing.  ld -r
--relax attempts to overcome the large section problem for branches by
inserting trampolines, but the powerpc support added lots of
unnecessary trampolines.  This patch trims them somewhat.

bfd/
	* elf32-ppc.c (ppc_elf_relax_section): Ignore common or undef locals.
	Avoid trashing toff with added when used as a symbol index.
	Ignore R_PPC_PLTREL24 addends in unused example code.  Avoid
	creating unnecessary fixups when relocatable.
ld/
	* testsuite/ld-powerpc/big.s: New file.
	* testsuite/ld-powerpc/relaxrl.d: New test.
	* testsuite/ld-powerpc/powerpc.exp: Run new test.
	* testsuite/ld-powerpc/relaxr.d: Adjust.

diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index 1ddfc6c1f4..c289eebe31 100644
--- a/bfd/elf32-ppc.c
+++ b/bfd/elf32-ppc.c
@@ -7386,12 +7386,10 @@ ppc_elf_relax_section (bfd *abfd,
 	    {
 	      if (tsec != NULL)
 		;
-	      else if (isym->st_shndx == SHN_UNDEF)
-		tsec = bfd_und_section_ptr;
 	      else if (isym->st_shndx == SHN_ABS)
 		tsec = bfd_abs_section_ptr;
-	      else if (isym->st_shndx == SHN_COMMON)
-		tsec = bfd_com_section_ptr;
+	      else
+		continue;
 
 	      toff = isym->st_value;
 	      sym_type = ELF_ST_TYPE (isym->st_info);
@@ -7533,6 +7531,17 @@ ppc_elf_relax_section (bfd *abfd,
 	  if (tsec == isec)
 	    continue;
 
+	  /* toff is used for the symbol index when the symbol is
+	     undefined and we're doing a relocatable link, so we can't
+	     support addends.  It would be possible to do so by
+	     putting the addend in one_branch_fixup but addends on
+	     branches are rare so it hardly seems worth supporting.  */
+	  if (bfd_link_relocatable (link_info)
+	      && tsec == bfd_und_section_ptr
+	      && r_type != R_PPC_PLTREL24
+	      && irel->r_addend != 0)
+	    continue;
+
 	  /* There probably isn't any reason to handle symbols in
 	     SEC_MERGE sections;  SEC_MERGE doesn't seem a likely
 	     attribute for a code section, and we are only looking at
@@ -7556,7 +7565,8 @@ ppc_elf_relax_section (bfd *abfd,
 		 a section symbol should not include the addend;  Such an
 		 access is presumed to be an offset from "sym";  The
 		 location of interest is just "sym".  */
-	      if (sym_type == STT_SECTION)
+	      if (sym_type == STT_SECTION
+		  && r_type != R_PPC_PLTREL24)
 		toff += irel->r_addend;
 
 	      toff
@@ -7564,7 +7574,8 @@ ppc_elf_relax_section (bfd *abfd,
 					      elf_section_data (tsec)->sec_info,
 					      toff);
 
-	      if (sym_type != STT_SECTION)
+	      if (sym_type != STT_SECTION
+		  && r_type != R_PPC_PLTREL24)
 		toff += irel->r_addend;
 	    }
 	  /* PLTREL24 addends are special.  */
@@ -7581,6 +7592,16 @@ ppc_elf_relax_section (bfd *abfd,
 
 	  roff = irel->r_offset;
 
+	  /* Avoid creating a lot of unnecessary fixups when
+	     relocatable if the output section size is such that a
+	     fixup can be created at final link.
+	     The max_branch_offset adjustment allows for some number
+	     of other fixups being needed at final link.  */
+	  if (bfd_link_relocatable (link_info)
+	      && (isec->output_section->rawsize - (isec->output_offset + roff)
+		  < max_branch_offset - (max_branch_offset >> 4)))
+	    continue;
+
 	  /* If the branch is in range, no need to do anything.  */
 	  if (tsec != bfd_und_section_ptr
 	      && (!bfd_link_relocatable (link_info)
diff --git a/ld/testsuite/ld-powerpc/big.s b/ld/testsuite/ld-powerpc/big.s
new file mode 100644
index 0000000000..e372c979ee
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/big.s
@@ -0,0 +1,2 @@
+ .text
+ .space 32*1024*1024
diff --git a/ld/testsuite/ld-powerpc/powerpc.exp b/ld/testsuite/ld-powerpc/powerpc.exp
index 0359ba28cb..cfeb277f04 100644
--- a/ld/testsuite/ld-powerpc/powerpc.exp
+++ b/ld/testsuite/ld-powerpc/powerpc.exp
@@ -160,6 +160,9 @@ set ppcelftests {
     {"relocatable relaxing" "-melf32ppc -r --relax" "" "-a32" "relax.s"
      {{objdump -dr relaxr.d}}
      "rrelax"}
+    {"relocatable relaxing large" "-melf32ppc -r --relax" "" "-a32" "relax.s big.s"
+     {{objdump -dr relaxrl.d}}
+     "rrelax"}
 }
 
 set ppc64elftests {
diff --git a/ld/testsuite/ld-powerpc/relaxr.d b/ld/testsuite/ld-powerpc/relaxr.d
index 3ce2751c15..1b3a3c147d 100644
--- a/ld/testsuite/ld-powerpc/relaxr.d
+++ b/ld/testsuite/ld-powerpc/relaxr.d
@@ -4,23 +4,13 @@
 Disassembly of section .text:
 
 00000000 <_start>:
-   0:	(48 00 00 15|15 00 00 48) 	bl      14 <_start\+0x14>
-   4:	(48 00 00 21|21 00 00 48) 	bl      24 <_start\+0x24>
-   8:	(48 00 00 0d|0d 00 00 48) 	bl      14 <_start\+0x14>
-			8: R_PPC_NONE	\*ABS\*
-   c:	(48 00 00 19|19 00 00 48) 	bl      24 <_start\+0x24>
-			c: R_PPC_NONE	\*ABS\*
+   0:	(48 00 00 01|01 00 00 48) 	bl      0 <_start>
+			0: R_PPC_REL24	near
+   4:	(48 00 00 01|01 00 00 48) 	bl      4 <_start\+0x4>
+			4: R_PPC_REL24	far
+   8:	(48 00 00 01|01 00 00 48) 	bl      8 <_start\+0x8>
+			8: R_PPC_REL24	near
+   c:	(48 00 00 01|01 00 00 48) 	bl      c <_start\+0xc>
+			c: R_PPC_REL24	far
   10:	(48 00 00 00|00 00 00 48) 	b       10 <_start\+0x10>
 			10: R_PPC_REL24	_start
-  14:	(3d 80 00 00|00 00 80 3d) 	lis     r12,0
-			1(6|4): R_PPC_ADDR16_HA	near
-  18:	(39 8c 00 00|00 00 8c 39) 	addi    r12,r12,0
-			1(a|8): R_PPC_ADDR16_LO	near
-  1c:	(7d 89 03 a6|a6 03 89 7d) 	mtctr   r12
-  20:	(4e 80 04 20|20 04 80 4e) 	bctr
-  24:	(3d 80 00 00|00 00 80 3d) 	lis     r12,0
-			2(6|4): R_PPC_ADDR16_HA	far
-  28:	(39 8c 00 00|00 00 8c 39) 	addi    r12,r12,0
-			2(a|8): R_PPC_ADDR16_LO	far
-  2c:	(7d 89 03 a6|a6 03 89 7d) 	mtctr   r12
-  30:	(4e 80 04 20|20 04 80 4e) 	bctr
diff --git a/ld/testsuite/ld-powerpc/relaxrl.d b/ld/testsuite/ld-powerpc/relaxrl.d
new file mode 100644
index 0000000000..8557e3fcfb
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/relaxrl.d
@@ -0,0 +1,27 @@
+
+.*:     file format .*
+
+Disassembly of section .text:
+
+0+ <_start>:
+ +0:	(48 00 00 15|15 00 00 48) 	bl      14 <_start\+0x14>
+ +4:	(48 00 00 21|21 00 00 48) 	bl      24 <_start\+0x24>
+ +8:	(48 00 00 0d|0d 00 00 48) 	bl      14 <_start\+0x14>
+			8: R_PPC_NONE	\*ABS\*
+ +c:	(48 00 00 19|19 00 00 48) 	bl      24 <_start\+0x24>
+			c: R_PPC_NONE	\*ABS\*
+ +10:	(48 00 00 00|00 00 00 48) 	b       10 <_start\+0x10>
+			10: R_PPC_REL24	_start
+ +14:	(3d 80 00 00|00 00 80 3d) 	lis     r12,0
+			1(6|4): R_PPC_ADDR16_HA	near
+ +18:	(39 8c 00 00|00 00 8c 39) 	addi    r12,r12,0
+			1(a|8): R_PPC_ADDR16_LO	near
+ +1c:	(7d 89 03 a6|a6 03 89 7d) 	mtctr   r12
+ +20:	(4e 80 04 20|20 04 80 4e) 	bctr
+ +24:	(3d 80 00 00|00 00 80 3d) 	lis     r12,0
+			2(6|4): R_PPC_ADDR16_HA	far
+ +28:	(39 8c 00 00|00 00 8c 39) 	addi    r12,r12,0
+			2(a|8): R_PPC_ADDR16_LO	far
+ +2c:	(7d 89 03 a6|a6 03 89 7d) 	mtctr   r12
+ +30:	(4e 80 04 20|20 04 80 4e) 	bctr
+	\.\.\.

-- 
Alan Modra
Australia Development Lab, IBM


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