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]

relaxing partial links


This patch allows partial links to be relaxed on PPC. This is a useful feature on vxworks, where kernel modules are partially linked object files, and may be loaded at addresses far away from the targets of branches. Furthermore the sections within such a kernel module can be arbitrarily placed at load time.

tested on powerpc-vxworks, ok?

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

2009-05-26  Nathan Sidwell  <nathan@codesourcery.com>

	bfd/
	* elf32-ppc.c (ppc_elf_relax_section): Work with a partial
	link.

	ld/
	* ldmain.c (main): Don't reject --relax -r.
	* ld.texinfo (PowerPC ELF32): Document behaviour of relaxing
	partial links.

	ld/testsuite/
	* ld-powerpc/vxworks-relax-2.s: New.
	* ld-powerpc/vxworks-relax-2.rd: New.
	* ld-powerpc/powerpc.exp: Add it.

Index: bfd/elf32-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-ppc.c,v
retrieving revision 1.253
diff -c -3 -p -r1.253 elf32-ppc.c
*** bfd/elf32-ppc.c	21 Mar 2009 02:35:27 -0000	1.253
--- bfd/elf32-ppc.c	26 May 2009 14:49:40 -0000
*************** ppc_elf_relax_section (bfd *abfd,
*** 5661,5666 ****
--- 5661,5672 ----
        || isec->reloc_count == 0)
      return TRUE;
  
+   /* We cannot represent the required PIC relocs in the output, so don't
+      do anything.  The linker doesn't support mixing -shared and -r
+      anyway.  */
+   if (link_info->relocatable && link_info->shared)
+      return TRUE;
+   
    trampoff = (isec->size + 3) & (bfd_vma) -4;
    /* Space for a branch around any trampolines.  */
    trampoff += 4;
*************** ppc_elf_relax_section (bfd *abfd,
*** 5726,5732 ****
  	    }
  	  isym = isymbuf + ELF32_R_SYM (irel->r_info);
  	  if (isym->st_shndx == SHN_UNDEF)
! 	    continue;	/* We can't do anything with undefined symbols.  */
  	  else if (isym->st_shndx == SHN_ABS)
  	    tsec = bfd_abs_section_ptr;
  	  else if (isym->st_shndx == SHN_COMMON)
--- 5732,5738 ----
  	    }
  	  isym = isymbuf + ELF32_R_SYM (irel->r_info);
  	  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)
*************** ppc_elf_relax_section (bfd *abfd,
*** 5779,5784 ****
--- 5785,5796 ----
  	      tsec = h->root.u.def.section;
  	      toff = h->root.u.def.value;
  	    }
+ 	  else if (h->root.type == bfd_link_hash_undefined
+ 		   || h->root.type == bfd_link_hash_undefweak)
+ 	    {
+ 	      tsec = bfd_und_section_ptr;
+ 	      toff = 0;
+ 	    }
  	  else
  	    continue;
  
*************** ppc_elf_relax_section (bfd *abfd,
*** 5838,5844 ****
        reladdr = isec->output_section->vma + isec->output_offset + roff;
  
        /* If the branch is in range, no need to do anything.  */
!       if (symaddr - reladdr + max_branch_offset < 2 * max_branch_offset)
  	continue;
  
        /* Look for an existing fixup to this address.  */
--- 5850,5861 ----
        reladdr = isec->output_section->vma + isec->output_offset + roff;
  
        /* If the branch is in range, no need to do anything.  */
!       if (tsec != bfd_und_section_ptr
! 	  && (!link_info->relocatable
! 	      /* 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.  */
*************** ppc_elf_relax_section (bfd *abfd,
*** 6048,6053 ****
--- 6065,6091 ----
      free (internal_relocs);
  
    *again = changes != 0;
+   if (!*again && link_info->relocatable)
+     {
+       /* Convert the internal relax relocs to external form.  */
+       for (irel = internal_relocs; irel < irelend; irel++)
+ 	if (ELF32_R_TYPE (irel->r_info) == R_PPC_RELAX32)
+ 	  {
+ 	    unsigned long r_symndx = ELF32_R_SYM (irel->r_info);
+ 
+ 	    /* Rewrite the reloc and convert one of the trailing nop
+ 	       relocs to describe this relocation.  */
+ 	    BFD_ASSERT (ELF32_R_TYPE (irelend[-1].r_info) == R_PPC_NONE);
+ 	    /* The relocs are at the bottom 2 bytes */
+ 	    irel[0].r_offset += 2;
+ 	    memmove (irel + 1, irel, (irelend - irel - 1) * sizeof (*irel));
+ 	    irel[0].r_info = ELF32_R_INFO (r_symndx, R_PPC_ADDR16_HA);
+ 	    irel[1].r_offset += 4;
+ 	    irel[1].r_info = ELF32_R_INFO (r_symndx, R_PPC_ADDR16_LO);
+ 	    irel++;
+ 	  }
+     }
+   
    return TRUE;
  
   error_return:
Index: ld/ld.texinfo
===================================================================
RCS file: /cvs/src/src/ld/ld.texinfo,v
retrieving revision 1.245
diff -c -3 -p -r1.245 ld.texinfo
*** ld/ld.texinfo	22 May 2009 11:58:44 -0000	1.245
--- ld/ld.texinfo	26 May 2009 14:49:53 -0000
*************** displacement, which may result in @comma
*** 6284,6290 ****
  @samp{--relax} enables the generation of trampolines that can access
  the entire 32-bit address space.  These trampolines are inserted at
  section boundaries, so may not themselves be reachable if an input
! section exceeds 33M in size.
  
  @cindex PowerPC ELF32 options
  @table @option
--- 6284,6293 ----
  @samp{--relax} enables the generation of trampolines that can access
  the entire 32-bit address space.  These trampolines are inserted at
  section boundaries, so may not themselves be reachable if an input
! section exceeds 33M in size.  You may combine @samp{-r} and
! @samp{--relax} to add trampolines in a partial link.  In that case
! both branches to undefined symbols and inter-section branches are also
! considered potentially out of range, and trampolines inserted.
  
  @cindex PowerPC ELF32 options
  @table @option
Index: ld/ldmain.c
===================================================================
RCS file: /cvs/src/src/ld/ldmain.c,v
retrieving revision 1.135
diff -c -3 -p -r1.135 ldmain.c
*** ld/ldmain.c	6 Apr 2009 00:47:09 -0000	1.135
--- ld/ldmain.c	26 May 2009 14:49:54 -0000
*************** main (int argc, char **argv)
*** 294,301 ****
      {
        if (command_line.check_section_addresses < 0)
  	command_line.check_section_addresses = 0;
-       if (command_line.relax)
- 	einfo (_("%P%F: --relax and -r may not be used together\n"));
        if (link_info.shared)
  	einfo (_("%P%F: -r and -shared may not be used together\n"));
      }
--- 294,299 ----
Index: ld/testsuite/ld-powerpc/powerpc.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-powerpc/powerpc.exp,v
retrieving revision 1.25
diff -c -3 -p -r1.25 powerpc.exp
*** ld/testsuite/ld-powerpc/powerpc.exp	4 Mar 2009 05:50:50 -0000	1.25
--- ld/testsuite/ld-powerpc/powerpc.exp	26 May 2009 14:49:57 -0000
*************** if {[istarget "*-*-vxworks"]} {
*** 54,59 ****
--- 54,64 ----
  	 "-mregnames" {vxworks-relax.s}
  	 {{readelf --relocs vxworks-relax.rd}}
  	 "vxworks-relax"}
+ 	{"VxWorks relocatable relax test"
+ 	 "-Tvxworks1.ld -r --relax -q"
+ 	 "-mregnames" {vxworks-relax-2.s}
+ 	 {{readelf --relocs vxworks-relax-2.rd}}
+ 	 "vxworks-relax-2"}
      }
      run_ld_link_tests $ppcvxtests
      run_dump_test "vxworks1-static"
Index: ld/testsuite/ld-powerpc/vxworks-relax-2.rd
===================================================================
RCS file: ld/testsuite/ld-powerpc/vxworks-relax-2.rd
diff -N ld/testsuite/ld-powerpc/vxworks-relax-2.rd
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-powerpc/vxworks-relax-2.rd	26 May 2009 14:49:58 -0000
***************
*** 0 ****
--- 1,11 ----
+ 
+ Relocation section '.rela.text' at offset 0x[0-9a-f]+ contains 8 entries:
+  Offset     Info    Type            Sym.Value  Sym. Name \+ Addend
+ 00000016  00000106 R_PPC_ADDR16_HA   00000000   .text \+ 4000034
+ 0000001a  00000104 R_PPC_ADDR16_LO   00000000   .text \+ 4000034
+ 00000006  00000106 R_PPC_ADDR16_HA   00000000   .text \+ 4000034
+ 0000000a  00000104 R_PPC_ADDR16_LO   00000000   .text \+ 4000034
+ 00000026  00000506 R_PPC_ADDR16_HA   00000000   undefined \+ 0
+ 0000002a  00000504 R_PPC_ADDR16_LO   00000000   undefined \+ 0
+ 0400003e  00000606 R_PPC_ADDR16_HA   00000000   _start \+ 0
+ 04000042  00000604 R_PPC_ADDR16_LO   00000000   _start \+ 0
Index: ld/testsuite/ld-powerpc/vxworks-relax-2.s
===================================================================
RCS file: ld/testsuite/ld-powerpc/vxworks-relax-2.s
diff -N ld/testsuite/ld-powerpc/vxworks-relax-2.s
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-powerpc/vxworks-relax-2.s	26 May 2009 14:49:58 -0000
***************
*** 0 ****
--- 1,14 ----
+ 	.globl	_start
+ _start:
+ 	bl	elsewhere
+ 	lis 9,elsewhere@ha
+         la 0,elsewhere@l(9)
+ 	bl	undefined
+ 
+ 
+ 	.section .far,"ax",@progbits
+ elsewhere:
+ 	bl	_start
+ 
+ 	.section .pad
+ 	.space 0x4000000

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