This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH] ld: Fix ALIGN_WITH_INPUT
- From: Sebastian Huber <sebastian dot huber at embedded-brains dot de>
- To: binutils at sourceware dot org
- Cc: Sebastian Huber <sebastian dot huber at embedded-brains dot de>
- Date: Thu, 30 Jan 2014 10:31:46 +0100
- Subject: [PATCH] ld: Fix ALIGN_WITH_INPUT
- Authentication-results: sourceware.org; auth=none
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