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]

[ppc] fix a couple of relax bugs


This patch fixes two relax bugs

1) the existing relaxation trampolines use r11 to generate the target address. r11 is also used by the ABI to call the out-of-line register save and restore routines. (And also for mcount). These routines are exceptions to the regular ABI. GCC can now emit calls to the ool save routines. As you can guess, when relaxing an executable where the save routines are too far away from the prologue they are called from, things go badly wrong :( AFAICT, r12 is an equally suitable temporary register, and is not used by such ABI exceptions.

2) I noticed the dire lack of testcases and added one. This caused me to notice the other bug in the recent patch of mine that allowed relaxing a relocatable link. We continued to use the target symbol's value to distinguish trampolines to different locations. For a relocatable link with undefined symbols these are all going to be zero, resuling in a single trampoline. oops! Fixed by using the symbol's offset in the input symbol table in this case. The reason I didn;t notice this originally is I was working with vxworks kernel modules. these are relocatable links but are provided with the kernel symbol information and thus don't have any undefined symbols.

tested on powerpc-elf, ok?

nathan

--
Nathan Sidwell    ::   http://www.codesourcery.com   ::         CodeSourcery

2009-08-10  Nathan Sidwell  <nathan@codesourcery.com>

	bfd/
	* elf32-ppc.c (shared_stub_entry, stub_entry): Use r12, not r11.
	(ppc_elf_relax_section): Use symbol index to distinguish
	relocatable stubs.

	ld/testsuite/
	* ld-powerpc/relax.s: New.
	* ld-powerpc/relax.d: New.
	* ld-powerpc/relaxr.d: New.
	* ld-powerpc/powerpc.exp: Add new tests.

Index: bfd/elf32-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-ppc.c,v
retrieving revision 1.266
diff -c -3 -p -r1.266 elf32-ppc.c
*** bfd/elf32-ppc.c	10 Aug 2009 07:24:33 -0000	1.266
--- bfd/elf32-ppc.c	10 Aug 2009 11:26:38 -0000
*************** ppc_elf_hash_symbol (struct elf_link_has
*** 5857,5879 ****
  
  #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
  
  static const int shared_stub_entry[] =
    {
      0x7c0802a6, /* mflr 0 */
      0x429f0005, /* bcl 20, 31, .Lxxx */
!     0x7d6802a6, /* mflr 11 */
!     0x3d6b0000, /* addis 11, 11, (xxx-.Lxxx)@ha */
!     0x396b0018, /* addi 11, 11, (xxx-.Lxxx)@l */
      0x7c0803a6, /* mtlr 0 */
!     0x7d6903a6, /* mtctr 11 */
      0x4e800420, /* bctr */
    };
  
  static const int stub_entry[] =
    {
!     0x3d600000, /* lis 11,xxx@ha */
!     0x396b0000, /* addi 11,11,xxx@l */
!     0x7d6903a6, /* mtctr 11 */
      0x4e800420, /* bctr */
    };
  
--- 5857,5881 ----
  
  #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
  
+ /* Relaxation trampolines.  r12 is available for clobbering (r11, is
+    used for some functions that are allowed to break the ABI).  */
  static const int shared_stub_entry[] =
    {
      0x7c0802a6, /* mflr 0 */
      0x429f0005, /* bcl 20, 31, .Lxxx */
!     0x7d8802a6, /* mflr 12 */
!     0x3d8c0000, /* addis 12, 12, (xxx-.Lxxx)@ha */
!     0x398c0008, /* addi 12, 12, (xxx-.Lxxx)@l */
      0x7c0803a6, /* mtlr 0 */
!     0x7d8903a6, /* mtctr 12 */
      0x4e800420, /* bctr */
    };
  
  static const int stub_entry[] =
    {
!     0x3d800000, /* lis 12,xxx@ha */
!     0x398c0000, /* addi 12,12,xxx@l */
!     0x7d8903a6, /* mtctr 12 */
      0x4e800420, /* bctr */
    };
  
*************** ppc_elf_relax_section (bfd *abfd,
*** 5887,5892 ****
--- 5889,5896 ----
    {
      struct one_fixup *next;
      asection *tsec;
+     /* Final link, can use the symbol offset.  For a
+        relocatable link we use the symbol's index.  */
      bfd_vma toff;
      bfd_vma trampoff;
    };
*************** ppc_elf_relax_section (bfd *abfd,
*** 5937,5943 ****
    for (irel = internal_relocs; irel < irelend; irel++)
      {
        unsigned long r_type = ELF32_R_TYPE (irel->r_info);
!       bfd_vma symaddr, reladdr, toff, roff;
        asection *tsec;
        struct one_fixup *f;
        size_t insn_offset = 0;
--- 5941,5947 ----
    for (irel = internal_relocs; irel < irelend; irel++)
      {
        unsigned long r_type = ELF32_R_TYPE (irel->r_info);
!       bfd_vma reladdr, toff, roff;
        asection *tsec;
        struct one_fixup *f;
        size_t insn_offset = 0;
*************** ppc_elf_relax_section (bfd *abfd,
*** 6019,6025 ****
  		   || h->root.type == bfd_link_hash_undefweak)
  	    {
  	      tsec = bfd_und_section_ptr;
! 	      toff = 0;
  	    }
  	  else
  	    continue;
--- 6023,6029 ----
  		   || h->root.type == bfd_link_hash_undefweak)
  	    {
  	      tsec = bfd_und_section_ptr;
! 	      toff = link_info->relocatable ? indx : 0;
  	    }
  	  else
  	    continue;
*************** ppc_elf_relax_section (bfd *abfd,
*** 6120,6127 ****
        if (tsec->output_section == NULL)
  	continue;
  
-       symaddr = tsec->output_section->vma + tsec->output_offset + toff;
- 
        roff = irel->r_offset;
        reladdr = isec->output_section->vma + isec->output_offset + roff;
  
--- 6124,6129 ----
*************** ppc_elf_relax_section (bfd *abfd,
*** 6131,6137 ****
  	      /* A relocatable link may have sections moved during
  		 final link, so do not presume they remain in range.  */
  	      || tsec->output_section == isec->output_section)
! 	  && symaddr - reladdr + max_branch_offset < 2 * max_branch_offset)
  	continue;
  
        /* Look for an existing fixup to this address.  */
--- 6133,6140 ----
  	      /* A relocatable link may have sections moved during
  		 final link, so do not presume they remain in range.  */
  	      || tsec->output_section == isec->output_section)
! 	  && (tsec->output_section->vma + tsec->output_offset + toff
! 	      - reladdr + max_branch_offset < 2 * max_branch_offset))
  	continue;
  
        /* Look for an existing fixup to this address.  */
Index: ld/testsuite/ld-powerpc/powerpc.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-powerpc/powerpc.exp,v
retrieving revision 1.26
diff -c -3 -p -r1.26 powerpc.exp
*** ld/testsuite/ld-powerpc/powerpc.exp	27 May 2009 13:31:24 -0000	1.26
--- ld/testsuite/ld-powerpc/powerpc.exp	10 Aug 2009 11:26:49 -0000
*************** set ppc64elftests {
*** 158,163 ****
--- 158,169 ----
        "tlsmark"}
      {"sym@tocbase" "-shared -melf64ppc" "-a64" {symtocbase-1.s symtocbase-2.s}
  	{{objdump -dj.data symtocbase.d}} "symtocbase.so"}
+     {"relaxing" "-melf32ppc --relax -Ttext=0 --defsym far=0x80001234 --defsym near=0x00004320" "" "relax.s"
+      {{objdump -dr relax.d}}
+       "relax"}
+     {"relocatable relaxing" "-melf32ppc -r --relax" "" "relax.s"
+      {{objdump -dr relaxr.d}}
+       "relax"}
  }
  
  
Index: ld/testsuite/ld-powerpc/relax.d
===================================================================
RCS file: ld/testsuite/ld-powerpc/relax.d
diff -N ld/testsuite/ld-powerpc/relax.d
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-powerpc/relax.d	10 Aug 2009 11:26:49 -0000
***************
*** 0 ****
--- 1,15 ----
+ 
+ .*:     file format .*
+ 
+ Disassembly of section .text:
+ 
+ 00000000 <_start>:
+    0:	48 00 43 21 	bl	4320 <near>
+    4:	48 00 00 11 	bl	14 <_start\+0x14>
+    8:	48 00 43 19 	bl	4320 <near>
+    c:	48 00 00 09 	bl	14 <_start\+0x14>
+   10:	48 00 00 14 	b	24 <.*>
+   14:	3d 80 80 00 	lis	r12,-32768
+   18:	39 8c 12 34 	addi	r12,r12,4660
+   1c:	7d 89 03 a6 	mtctr	r12
+   20:	4e 80 04 20 	bctr
Index: ld/testsuite/ld-powerpc/relax.s
===================================================================
RCS file: ld/testsuite/ld-powerpc/relax.s
diff -N ld/testsuite/ld-powerpc/relax.s
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-powerpc/relax.s	10 Aug 2009 11:26:49 -0000
***************
*** 0 ****
--- 1,6 ----
+ 	.globl _start
+ _start:
+ 	bl near
+ 	bl far
+ 	bl near
+ 	bl far
Index: ld/testsuite/ld-powerpc/relaxr.d
===================================================================
RCS file: ld/testsuite/ld-powerpc/relaxr.d
diff -N ld/testsuite/ld-powerpc/relaxr.d
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-powerpc/relaxr.d	10 Aug 2009 11:26:49 -0000
***************
*** 0 ****
--- 1,25 ----
+ 
+ .*:     file format .*
+ 
+ Disassembly of section .text:
+ 
+ 00000000 <_start>:
+    0:	48 00 00 15 	bl	14 <_start\+0x14>
+    4:	48 00 00 21 	bl	24 <_start\+0x24>
+    8:	48 00 00 0d 	bl	14 <_start\+0x14>
+ 			8: R_PPC_NONE	\*ABS\*
+    c:	48 00 00 19 	bl	24 <_start\+0x24>
+ 			c: R_PPC_NONE	\*ABS\*
+   10:	48 00 00 24 	b	34 <_start\+0x34>
+   14:	3d 80 00 00 	lis	r12,0
+ 			16: R_PPC_ADDR16_HA	near
+   18:	39 8c 00 00 	addi	r12,r12,0
+ 			1a: R_PPC_ADDR16_LO	near
+   1c:	7d 89 03 a6 	mtctr	r12
+   20:	4e 80 04 20 	bctr
+   24:	3d 80 00 00 	lis	r12,0
+ 			26: R_PPC_ADDR16_HA	far
+   28:	39 8c 00 00 	addi	r12,r12,0
+ 			2a: R_PPC_ADDR16_LO	far
+   2c:	7d 89 03 a6 	mtctr	r12
+   30:	4e 80 04 20 	bctr

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