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]

Re: ARM linker stub changes - placement, PIC


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

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