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]

[PATCH] ld: Fix ALIGN_WITH_INPUT


I added the ALIGN_WITH_INPUT linker language feature to deal with the
problems described here:

https://sourceware.org/ml/binutils/2013-06/msg00246.html

Unfortuntely I missed some corner cases.  The key point is not that VMA
and LMA are aligned with the same values, but that the difference
between the VMA and LMA remains intact so that a simple memcpy()
operation works.

The new test cases highlight the corner cases.

ld/ChangeLog
2014-01-30  Sebastian Huber  <sebastian.huber@embedded-brains.de>

	* ld/ld.texinfo: Change ALIGN_WITH_INPUT documentation.
	* ld/ldlang.c (lang_size_sections_1): Add dotdelta
	variable which reflects the VMA change due to alignment
	requirements.  Use dotdelta do change the LMA if
	ALIGN_WITH_INPUT is requested.

ld/testsuite/ChangeLog
2014-01-30  Sebastian Huber  <sebastian.huber@embedded-brains.de>

	* ld-scripts/rgn-at9.d: New file.
	* ld-scripts/rgn-at9.t: Likewise.
	* ld-scripts/rgn-at10.d: Likewise.
	* ld-scripts/rgn-at10.s: Likewise.
	* ld-scripts/rgn-at10.t: Likewise.
	* ld-scripts/rgn-at11.d: Likewise.
	* ld-scripts/rgn-at11.t: Likewise.
---
 ld/ld.texinfo                      |    6 +---
 ld/ldlang.c                        |   42 ++++++++++++++++++++++-------------
 ld/testsuite/ld-scripts/rgn-at10.d |   12 ++++++++++
 ld/testsuite/ld-scripts/rgn-at10.s |   10 ++++++++
 ld/testsuite/ld-scripts/rgn-at10.t |   13 +++++++++++
 ld/testsuite/ld-scripts/rgn-at11.d |   11 +++++++++
 ld/testsuite/ld-scripts/rgn-at11.t |   13 +++++++++++
 ld/testsuite/ld-scripts/rgn-at9.d  |   10 ++++++++
 ld/testsuite/ld-scripts/rgn-at9.t  |   12 ++++++++++
 9 files changed, 109 insertions(+), 20 deletions(-)
 create mode 100644 ld/testsuite/ld-scripts/rgn-at10.d
 create mode 100644 ld/testsuite/ld-scripts/rgn-at10.s
 create mode 100644 ld/testsuite/ld-scripts/rgn-at10.t
 create mode 100644 ld/testsuite/ld-scripts/rgn-at11.d
 create mode 100644 ld/testsuite/ld-scripts/rgn-at11.t
 create mode 100644 ld/testsuite/ld-scripts/rgn-at9.d
 create mode 100644 ld/testsuite/ld-scripts/rgn-at9.t

diff --git a/ld/ld.texinfo b/ld/ld.texinfo
index a8e5ea6..d449f35 100644
--- a/ld/ld.texinfo
+++ b/ld/ld.texinfo
@@ -4605,10 +4605,8 @@ for (dst = &_bstart; dst< &_bend; dst++)
 @cindex forcing output section alignment
 @cindex output section alignment
 You can increase an output section's alignment by using ALIGN.  As an
-alternative you can force the output section alignment to the maximum alignment
-of all its input sections with ALIGN_WITH_INPUT.  The alignment forced by
-ALIGN_WITH_INPUT is used even in case the load and virtual memory regions are
-different.
+alternative you can enforce that the difference between the VMA and LMA remains
+intact throughout this output section with the ALIGN_WITH_INPUT attribute.
 
 @node Forced Input Alignment
 @subsubsection Forced Input Alignment
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 9903f70..4768af7 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -4808,7 +4808,7 @@ lang_size_sections_1
 	{
 	case lang_output_section_statement_enum:
 	  {
-	    bfd_vma newdot, after;
+	    bfd_vma newdot, after, dotdelta;
 	    lang_output_section_statement_type *os;
 	    lang_memory_region_type *r;
 	    int section_alignment = 0;
@@ -4874,6 +4874,7 @@ lang_size_sections_1
 	      }
 
 	    newdot = dot;
+	    dotdelta = 0;
 	    if (bfd_is_abs_section (os->bfd_section))
 	      {
 		/* No matter what happens, an abs section starts at zero.  */
@@ -4942,13 +4943,14 @@ lang_size_sections_1
 		    bfd_vma savedot = newdot;
 		    newdot = align_power (newdot, section_alignment);
 
-		    if (newdot != savedot
+		    dotdelta = newdot - savedot;
+		    if (dotdelta != 0
 			&& (config.warn_section_align
 			    || os->addr_tree != NULL)
 			&& expld.phase != lang_mark_phase_enum)
 		      einfo (_("%P: warning: changing start of section"
 			       " %s by %lu bytes\n"),
-			     os->name, (unsigned long) (newdot - savedot));
+			     os->name, (unsigned long) dotdelta);
 		  }
 
 		bfd_set_section_vma (0, os->bfd_section, newdot);
@@ -4996,15 +4998,20 @@ lang_size_sections_1
 	      {
 		bfd_vma lma = os->lma_region->current;
 
-		/* When LMA_REGION is the same as REGION, align the LMA
-		   as we did for the VMA, possibly including alignment
-		   from the bfd section.  If a different region, then
-		   only align according to the value in the output
-		   statement unless specified otherwise.  */
-		if (os->lma_region != os->region && !os->align_lma_with_input)
-		  section_alignment = os->section_alignment;
-		if (section_alignment > 0)
-		  lma = align_power (lma, section_alignment);
+		if (os->align_lma_with_input)
+		  lma += dotdelta;
+		else
+		  {
+		    /* When LMA_REGION is the same as REGION, align the LMA
+		       as we did for the VMA, possibly including alignment
+		       from the bfd section.  If a different region, then
+		       only align according to the value in the output
+		       statement.  */
+		    if (os->lma_region != os->region)
+		      section_alignment = os->section_alignment;
+		    if (section_alignment > 0)
+		      lma = align_power (lma, section_alignment);
+		  }
 		os->bfd_section->lma = lma;
 	      }
 	    else if (r->last_os != NULL
@@ -5080,7 +5087,10 @@ lang_size_sections_1
 	    if ((os->bfd_section->flags & SEC_HAS_CONTENTS) != 0
 		|| (os->bfd_section->flags & SEC_THREAD_LOCAL) == 0
 		|| link_info.relocatable)
-	      dot += TO_ADDR (os->bfd_section->size);
+	      dotdelta = TO_ADDR (os->bfd_section->size);
+	    else
+	      dotdelta = 0;
+	    dot += dotdelta;
 
 	    if (os->update_dot_tree != 0)
 	      exp_fold_tree (os->update_dot_tree, bfd_abs_section_ptr, &dot);
@@ -5100,10 +5110,10 @@ lang_size_sections_1
 				   os->bfd_section->vma);
 
 		if (os->lma_region != NULL && os->lma_region != os->region
-		    && (os->bfd_section->flags & SEC_LOAD))
+		    && ((os->bfd_section->flags & SEC_LOAD)
+			|| os->align_lma_with_input))
 		  {
-		    os->lma_region->current
-		      = os->bfd_section->lma + TO_ADDR (os->bfd_section->size);
+		    os->lma_region->current = os->bfd_section->lma + dotdelta;
 
 		    if (check_regions)
 		      os_region_check (os, os->lma_region, NULL,
diff --git a/ld/testsuite/ld-scripts/rgn-at10.d b/ld/testsuite/ld-scripts/rgn-at10.d
new file mode 100644
index 0000000..73ebfcc
--- /dev/null
+++ b/ld/testsuite/ld-scripts/rgn-at10.d
@@ -0,0 +1,12 @@
+#source: rgn-at10.s
+#ld: -T rgn-at10.t
+#objdump: -h --wide
+#xfail: rx-*-*
+# Test that lma is adjusted in case the section start vma is aligned and
+# lma_region != region if requested by script.  Make sure this works with
+# non-load sections.
+
+#...
+.* 0+10000 +0+20000 .*
+.* 0+10100 +0+20100 .*
+.* 0+10100 +0+20100 .*
diff --git a/ld/testsuite/ld-scripts/rgn-at10.s b/ld/testsuite/ld-scripts/rgn-at10.s
new file mode 100644
index 0000000..b538205
--- /dev/null
+++ b/ld/testsuite/ld-scripts/rgn-at10.s
@@ -0,0 +1,10 @@
+ .text
+ .long 0
+
+ .section .tbss,"awT",%nobits
+ .p2align 8
+ .zero 4
+
+ .data
+ .p2align 4
+ .long 0
diff --git a/ld/testsuite/ld-scripts/rgn-at10.t b/ld/testsuite/ld-scripts/rgn-at10.t
new file mode 100644
index 0000000..0aa0b27
--- /dev/null
+++ b/ld/testsuite/ld-scripts/rgn-at10.t
@@ -0,0 +1,13 @@
+MEMORY
+{
+  ram : ORIGIN = 0x10000, LENGTH = 0x10000
+  rom : ORIGIN = 0x20000, LENGTH = 0x10000
+}
+
+SECTIONS
+{
+  .text : ALIGN_WITH_INPUT {*(.text)} > ram AT> rom
+  .tbss : ALIGN_WITH_INPUT {*(.tbss)} > ram AT> rom
+  .data : ALIGN_WITH_INPUT {*(.data)} > ram AT> rom
+  /DISCARD/ : {*(*)}
+}
diff --git a/ld/testsuite/ld-scripts/rgn-at11.d b/ld/testsuite/ld-scripts/rgn-at11.d
new file mode 100644
index 0000000..9ebbd28
--- /dev/null
+++ b/ld/testsuite/ld-scripts/rgn-at11.d
@@ -0,0 +1,11 @@
+#source: rgn-at10.s
+#ld: -T rgn-at11.t
+#objdump: -h --wide
+#xfail: rx-*-*
+# Test that lma is not adjusted in case the section start vma is aligned and
+# lma_region != region if not requested by script.
+
+#...
+.* 0+10000 +0+20000 .*
+.* 0+10100 +0+20004 .*
+.* 0+10100 +0+20004 .*
diff --git a/ld/testsuite/ld-scripts/rgn-at11.t b/ld/testsuite/ld-scripts/rgn-at11.t
new file mode 100644
index 0000000..4f07c9d
--- /dev/null
+++ b/ld/testsuite/ld-scripts/rgn-at11.t
@@ -0,0 +1,13 @@
+MEMORY
+{
+  ram : ORIGIN = 0x10000, LENGTH = 0x10000
+  rom : ORIGIN = 0x20000, LENGTH = 0x10000
+}
+
+SECTIONS
+{
+  .text : ALIGN_WITH_INPUT {*(.text)} > ram AT> rom
+  .tbss : {*(.tbss)} > ram AT> rom
+  .data : ALIGN_WITH_INPUT {*(.data)} > ram AT> rom
+  /DISCARD/ : {*(*)}
+}
diff --git a/ld/testsuite/ld-scripts/rgn-at9.d b/ld/testsuite/ld-scripts/rgn-at9.d
new file mode 100644
index 0000000..e6384b4
--- /dev/null
+++ b/ld/testsuite/ld-scripts/rgn-at9.d
@@ -0,0 +1,10 @@
+#source: rgn-at6.s
+#ld: -T rgn-at9.t
+#objdump: -h --wide
+#xfail: rx-*-*
+# Test that lma is adjusted in case the section start vma is aligned and
+# lma_region != region if requested by script.
+
+#...
+.* 0+10000 +0+20080 .*
+.* 0+10100 +0+20180 .*
diff --git a/ld/testsuite/ld-scripts/rgn-at9.t b/ld/testsuite/ld-scripts/rgn-at9.t
new file mode 100644
index 0000000..7342e64
--- /dev/null
+++ b/ld/testsuite/ld-scripts/rgn-at9.t
@@ -0,0 +1,12 @@
+MEMORY
+{
+  ram : ORIGIN = 0x10000, LENGTH = 0x10000
+  rom : ORIGIN = 0x20080, LENGTH = 0x10000
+}
+
+SECTIONS
+{
+  .text : ALIGN_WITH_INPUT {*(.text)} > ram AT> rom
+  .data : ALIGN_WITH_INPUT {*(.data)} > ram AT> rom
+  /DISCARD/ : {*(*)}
+}
-- 
1.7.7


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