This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[ppc] fix a couple of relax bugs
- From: Nathan Sidwell <nathan at codesourcery dot com>
- To: binutils <binutils at sources dot redhat dot com>
- Date: Mon, 10 Aug 2009 13:00:43 +0100
- Subject: [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