This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: ARM linker stub changes - placement, PIC
- From: Christophe LYON <christophe dot lyon at st dot com>
- To: binutils at sourceware dot org
- Date: Wed, 04 Mar 2009 17:56:51 +0100
- Subject: Re: ARM linker stub changes - placement, PIC
- References: <20090224030947.GA24046@caradoc.them.org> <49A401A6.8060207@st.com> <20090224144458.GB5179@caradoc.them.org> <49A55915.4000405@st.com> <20090225153148.GA6768@caradoc.them.org> <49A5677D.9090006@st.com>
Hi all,
While reviewing Joseph's patch to insert stubs after input sections, I
have missed the fact that he didn't take the 'next' section size into
account before accepting it in the current group to share stubs.
In short, if we have:
a.o: (.text section)
call foo
b.o: (.text section)
[huge amount of code]
call foo
and foo is located far away, the current linker will try to insert stubs
after b.o, and a.o's call will be to far from the stub.
With the proposed fix, the stubs will be inserted between the 2
contributions.
Christophe.
2009-03-04 Christophe Lyon <christophe.lyon@st.com>
bfd/
* elf32-arm.c (group_sections): Take next section size into
account before accepting to group it.
testsuite/
* ld-arm/arm-elf.exp: Add new farcall-group-limit test.
* ld-arm/farcall-group-limit.d: New file.
* ld-arm/farcall-group3.s: New file.
* ld-arm/farcall-group4.s: New file.
Index: bfd/elf32-arm.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-arm.c,v
retrieving revision 1.178
diff -u -p -r1.178 elf32-arm.c
--- bfd/elf32-arm.c 26 Feb 2009 15:37:52 -0000 1.178
+++ bfd/elf32-arm.c 4 Mar 2009 16:49:42 -0000
@@ -3535,11 +3535,20 @@ group_sections (struct elf32_arm_link_ha
bfd_size_type total;
curr = head;
- total = head->size;
- while ((next = NEXT_SEC (curr)) != NULL
- && ((total += next->output_offset - curr->output_offset)
- < stub_group_size))
+ total = 0;
+ while ((next = NEXT_SEC (curr)) != NULL)
+ {
+ if ( (total + next->output_offset - curr->output_offset
+ + next->size)
+ < stub_group_size )
+ {
+ total += next->output_offset - curr->output_offset;
+ }
+ else
+ break;
+
curr = next;
+ }
/* OK, the size from the start to the start of CURR is less
than stub_group_size and thus can be handled by one stub
@@ -3560,11 +3569,18 @@ group_sections (struct elf32_arm_link_ha
bytes after the stub section can be handled by it too. */
if (!stubs_always_after_branch)
{
- total = 0;
- while (next != NULL
- && ((total += next->output_offset - head->output_offset)
- < stub_group_size))
+ total = head->size;
+ while (next != NULL)
{
+ if ( (total + next->output_offset - head->output_offset
+ + next->size)
+ < stub_group_size )
+ {
+ total += next->output_offset - head->output_offset;
+ }
+ else
+ break;
+
head = next;
next = NEXT_SEC (head);
htab->stub_group[head->id].link_sec = curr;
Index: ld/testsuite/ld-arm/arm-elf.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-arm/arm-elf.exp,v
retrieving revision 1.49
diff -u -p -r1.49 arm-elf.exp
--- ld/testsuite/ld-arm/arm-elf.exp 26 Feb 2009 15:37:53 -0000 1.49
+++ ld/testsuite/ld-arm/arm-elf.exp 4 Mar 2009 16:49:45 -0000
@@ -338,6 +338,11 @@ set armeabitests {
{"Group size=2" "-Ttext 0x1000 --section-start .foo=0x2003020 --stub-group-size=2" "" {farcall-group.s farcall-group2.s}
{{objdump -d farcall-group-size2.d}}
"farcall-group-size2"}
+
+ {"Group size limit" "-Ttext 0x1000 --section-start .far=0x2003020" "" {farcall-group3.s farcall-group4.s}
+ {{objdump -d farcall-group-limit.d}}
+ "farcall-group-limit"}
+
}
run_ld_link_tests $armeabitests
Index: ld/testsuite/ld-arm/farcall-group-limit.d
===================================================================
RCS file: ld/testsuite/ld-arm/farcall-group-limit.d
diff -N ld/testsuite/ld-arm/farcall-group-limit.d
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-arm/farcall-group-limit.d 4 Mar 2009 16:49:45 -0000
@@ -0,0 +1,21 @@
+
+.*: file format .*
+
+Disassembly of section .text:
+
+00001000 <_start>:
+ 1000: eb000000 bl 1008 <__bar_veneer>
+ 1004: 00000000 andeq r0, r0, r0
+
+00001008 <__bar_veneer>:
+ 1008: e51ff004 ldr pc, \[pc, #-4\] ; 100c <__bar_veneer\+0x4>
+ 100c: 02003020 .word 0x02003020
+
+00001010 <myfunc>:
+ ...
+ 2001010: eb000802 bl 2003020 <bar>
+
+Disassembly of section .far:
+
+02003020 <bar>:
+ 2003020: e12fff1e bx lr
Index: ld/testsuite/ld-arm/farcall-group3.s
===================================================================
RCS file: ld/testsuite/ld-arm/farcall-group3.s
diff -N ld/testsuite/ld-arm/farcall-group3.s
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-arm/farcall-group3.s 4 Mar 2009 16:49:45 -0000
@@ -0,0 +1,7 @@
+@ Test to ensure that ARM calls exceeding 32Mb generate stubs. FIXME
+
+ .text
+ .global bar
+ .global _start
+_start:
+ bl bar
Index: ld/testsuite/ld-arm/farcall-group4.s
===================================================================
RCS file: ld/testsuite/ld-arm/farcall-group4.s
diff -N ld/testsuite/ld-arm/farcall-group4.s
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-arm/farcall-group4.s 4 Mar 2009 16:49:45 -0000
@@ -0,0 +1,11 @@
+@ Test to ensure that ARM calls exceeding 32Mb generate stubs. FIXME
+
+ .text
+myfunc:
+ .space 0x2000000
+ bl bar
+
+ .section .far, "xa"
+ .global bar
+bar:
+ bx lr