This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH] [LD] Add ALIGN_WITH_INPUT output section attribute
- 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, 27 Jun 2013 16:17:49 +0200
- Subject: [PATCH] [LD] Add ALIGN_WITH_INPUT output section attribute
With this change
http://sourceware.org/ml/binutils/2013-03/msg00025.html
it is no longer possible to use constructs like this:
SECTIONS {
.a : {
begin = .;
*(.a)
} > VMA_REGION AT > LMA_REGION
.b : {
*(.b)
} > VMA_REGION AT > LMA_REGION
.c : {
*(.c)
end = .;
} > VMA_REGION AT > LMA_REGION
size = end - begin;
load_begin = LOADADDR (.a);
load_end = load_begin + size;
}
Assume that the .a, .b and .c have different alignment requirements and
that regions VMA_REGION and LMA_REGION are different. The load area of
the three sections is glued together with this change, but the runtime
area has gaps between the sections due to the different alignment
requirements.
Now a memcpy(begin, load_begin, size) no longer works.
A new ALIGN_WITH_INPUT attribute is introduced to help here which
restores the LD behaviour prior to Binutils 2.23.2.
SECTIONS {
.a : ALIGN_WITH_INPUT {
begin = .;
*(.a)
} > VMA_REGION AT > LMA_REGION
.b : ALIGN_WITH_INPUT {
*(.b)
} > VMA_REGION AT > LMA_REGION
.c : ALIGN_WITH_INPUT {
*(.c)
end = .;
} > VMA_REGION AT > LMA_REGION
size = end - begin;
load_begin = LOADADDR (.a);
load_end = load_begin + size;
}
The new test align-with-input.t uses an XFAIL. Is it possible to scan
the LD ouput for the presence of a certain error message?
ld/ChangeLog
2013-06-27 Sebastian Huber <sebastian.huber@embedded-brains.de>
* ldgram.y: Add ALIGN_WITH_INPUT output section attribute.
* ldlang.c: Likewise.
* ldlang.h: Likewise.
* ldlex.l: Likewise.
* mri.c: Likewise.
* ld.texinfo: Document new feature.
* NEWS: Mention new feature.
ld/testsuite/ChangeLog
2013-06-27 Sebastian Huber <sebastian.huber@embedded-brains.de>
* ld-scripts/script.exp: Run align with input test.
* ld-scripts/align-with-input.t: New file.
* ld-scripts/rgn-at8.d: Likewise.
* ld-scripts/rgn-at8.t: Likewise.
---
ld/NEWS | 3 +++
ld/ld.texinfo | 8 ++++++--
ld/ldgram.y | 14 ++++++++++----
ld/ldlang.c | 15 ++++++++++-----
ld/ldlang.h | 4 +++-
ld/ldlex.l | 1 +
ld/mri.c | 2 +-
ld/testsuite/ld-scripts/align-with-input.t | 5 +++++
ld/testsuite/ld-scripts/rgn-at8.d | 9 +++++++++
ld/testsuite/ld-scripts/rgn-at8.t | 12 ++++++++++++
ld/testsuite/ld-scripts/script.exp | 8 ++++++++
11 files changed, 68 insertions(+), 13 deletions(-)
create mode 100644 ld/testsuite/ld-scripts/align-with-input.t
create mode 100644 ld/testsuite/ld-scripts/rgn-at8.d
create mode 100644 ld/testsuite/ld-scripts/rgn-at8.t
diff --git a/ld/NEWS b/ld/NEWS
index 34b494a..d79c78f 100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -12,6 +12,9 @@
* Remove linker support for MIPS ECOFF targets.
+* Add ALIGN_WITH_INPUT to the linker script language to force the alignment of
+ an output section to use the maximum alignment of all its input sections.
+
Changes in 2.23:
* Enable compressed debug section feature for x86/x86_64 pe-coff.
diff --git a/ld/ld.texinfo b/ld/ld.texinfo
index d783ca9..986194b 100644
--- a/ld/ld.texinfo
+++ b/ld/ld.texinfo
@@ -3762,7 +3762,7 @@ The full description of an output section looks like this:
@group
@var{section} [@var{address}] [(@var{type})] :
[AT(@var{lma})]
- [ALIGN(@var{section_align})]
+ [ALIGN(@var{section_align}) | ALIGN_WITH_INPUT]
[SUBALIGN(@var{subsection_align})]
[@var{constraint}]
@{
@@ -4585,7 +4585,11 @@ for (dst = &_bstart; dst< &_bend; dst++)
@kindex ALIGN(@var{section_align})
@cindex forcing output section alignment
@cindex output section alignment
-You can increase an output section's alignment by using ALIGN.
+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.
@node Forced Input Alignment
@subsubsection Forced Input Alignment
diff --git a/ld/ldgram.y b/ld/ldgram.y
index ee88196..b74d921 100644
--- a/ld/ldgram.y
+++ b/ld/ldgram.y
@@ -147,14 +147,14 @@ static int error_index;
%token ORIGIN FILL
%token LENGTH CREATE_OBJECT_SYMBOLS INPUT GROUP OUTPUT CONSTRUCTORS
%token ALIGNMOD AT SUBALIGN HIDDEN PROVIDE PROVIDE_HIDDEN AS_NEEDED
-%type <token> assign_op atype attributes_opt sect_constraint
+%type <token> assign_op atype attributes_opt sect_constraint opt_align_with_input
%type <name> filename
%token CHIP LIST SECT ABSOLUTE LOAD NEWLINE ENDWORD ORDER NAMEWORD ASSERT_K
%token FORMAT PUBLIC DEFSYMEND BASE ALIAS TRUNCATE REL
%token INPUT_SCRIPT INPUT_MRI_SCRIPT INPUT_DEFSYM CASE EXTERN START
%token <name> VERS_TAG VERS_IDENTIFIER
%token GLOBAL LOCAL VERSIONK INPUT_VERSION_SCRIPT
-%token KEEP ONLY_IF_RO ONLY_IF_RW SPECIAL INPUT_SECTION_FLAGS
+%token KEEP ONLY_IF_RO ONLY_IF_RW SPECIAL INPUT_SECTION_FLAGS ALIGN_WITH_INPUT
%token EXCLUDE_FILE
%token CONSTANT
%type <versyms> vers_defns
@@ -1030,6 +1030,11 @@ opt_align:
| { $$ = 0; }
;
+opt_align_with_input:
+ ALIGN_WITH_INPUT { $$ = ALIGN_WITH_INPUT; }
+ | { $$ = 0; }
+ ;
+
opt_subalign:
SUBALIGN '(' exp ')' { $$ = $3; }
| { $$ = 0; }
@@ -1046,20 +1051,21 @@ section: NAME { ldlex_expression(); }
opt_exp_with_type
opt_at
opt_align
+ opt_align_with_input
opt_subalign { ldlex_popstate (); ldlex_script (); }
sect_constraint
'{'
{
lang_enter_output_section_statement($1, $3,
sectype,
- $5, $6, $4, $8);
+ $5, $7, $4, $9, $6);
}
statement_list_opt
'}' { ldlex_popstate (); ldlex_expression (); }
memspec_opt memspec_at_opt phdr_opt fill_opt
{
ldlex_popstate ();
- lang_leave_output_section_statement ($17, $14, $16, $15);
+ lang_leave_output_section_statement ($18, $15, $17, $16);
}
opt_comma
{}
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 645c26c..d60f248 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -1779,7 +1779,7 @@ lang_insert_orphan (asection *s,
os_tail = ((lang_output_section_statement_type **)
lang_output_section_statement.tail);
os = lang_enter_output_section_statement (secname, address, normal_section,
- NULL, NULL, NULL, constraint);
+ NULL, NULL, NULL, constraint, 0);
ps = NULL;
if (config.build_constructors && *os_tail == os)
@@ -4967,8 +4967,8 @@ lang_size_sections_1
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)
+ 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);
@@ -6235,7 +6235,8 @@ lang_enter_output_section_statement (const char *output_section_statement_name,
etree_type *align,
etree_type *subalign,
etree_type *ebase,
- int constraint)
+ int constraint,
+ int align_with_input)
{
lang_output_section_statement_type *os;
@@ -6257,6 +6258,10 @@ lang_enter_output_section_statement (const char *output_section_statement_name,
/* Make next things chain into subchain of this. */
push_stat_ptr (&os->children);
+ os->align_lma_with_input = align_with_input == ALIGN_WITH_INPUT;
+ if (os->align_lma_with_input && align != NULL)
+ einfo (_("%F%P:%S: error: align with input and explicit align specified\n"), NULL);
+
os->subsection_alignment =
topower (exp_get_value_int (subalign, -1, "subsection alignment"));
os->section_alignment =
@@ -7307,7 +7312,7 @@ lang_enter_overlay_section (const char *name)
etree_type *size;
lang_enter_output_section_statement (name, overlay_vma, overlay_section,
- 0, overlay_subalign, 0, 0);
+ 0, overlay_subalign, 0, 0, 0);
/* If this is the first section, then base the VMA of future
sections on this one. This will work correctly even if `.' is
diff --git a/ld/ldlang.h b/ld/ldlang.h
index 00e3757..de177ef 100644
--- a/ld/ldlang.h
+++ b/ld/ldlang.h
@@ -167,6 +167,8 @@ typedef struct lang_output_section_statement_struct
unsigned int update_dot : 1;
/* If this section is after assignment to _end. */
unsigned int after_end : 1;
+ /* If this section uses the alignment of its input sections. */
+ unsigned int align_lma_with_input : 1;
} lang_output_section_statement_type;
typedef struct
@@ -507,7 +509,7 @@ extern lang_output_section_statement_type *lang_enter_output_section_statement
enum section_type sectype,
etree_type *align,
etree_type *subalign,
- etree_type *, int);
+ etree_type *, int, int align_with_input);
extern void lang_final
(void);
extern void lang_relax_sections
diff --git a/ld/ldlex.l b/ld/ldlex.l
index abe31c0..7d8e33b 100644
--- a/ld/ldlex.l
+++ b/ld/ldlex.l
@@ -319,6 +319,7 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)*
<EXPRESSION,BOTH,SCRIPT>"INCLUDE" { RTOKEN(INCLUDE);}
<BOTH,SCRIPT>"PHDRS" { RTOKEN (PHDRS); }
<EXPRESSION,BOTH,SCRIPT>"AT" { RTOKEN(AT);}
+<EXPRESSION,BOTH,SCRIPT>"ALIGN_WITH_INPUT" { RTOKEN(ALIGN_WITH_INPUT);}
<EXPRESSION,BOTH,SCRIPT>"SUBALIGN" { RTOKEN(SUBALIGN);}
<EXPRESSION,BOTH,SCRIPT>"HIDDEN" { RTOKEN(HIDDEN); }
<EXPRESSION,BOTH,SCRIPT>"PROVIDE" { RTOKEN(PROVIDE); }
diff --git a/ld/mri.c b/ld/mri.c
index fc7076a..450cdf7 100644
--- a/ld/mri.c
+++ b/ld/mri.c
@@ -208,7 +208,7 @@ mri_draw_tree (void)
lang_enter_output_section_statement (p->name, base,
p->ok_to_load ? normal_section : noload_section,
- align, subalign, NULL, 0);
+ align, subalign, NULL, 0, 0);
base = 0;
tmp = (struct wildcard_list *) xmalloc (sizeof *tmp);
tmp->next = NULL;
diff --git a/ld/testsuite/ld-scripts/align-with-input.t b/ld/testsuite/ld-scripts/align-with-input.t
new file mode 100644
index 0000000..616061c
--- /dev/null
+++ b/ld/testsuite/ld-scripts/align-with-input.t
@@ -0,0 +1,5 @@
+SECTIONS {
+ .abc : ALIGN(1) ALIGN_WITH_INPUT {
+ *(.abc)
+ }
+}
diff --git a/ld/testsuite/ld-scripts/rgn-at8.d b/ld/testsuite/ld-scripts/rgn-at8.d
new file mode 100644
index 0000000..c9d6350
--- /dev/null
+++ b/ld/testsuite/ld-scripts/rgn-at8.d
@@ -0,0 +1,9 @@
+#source: rgn-at6.s
+#ld: -T rgn-at8.t
+#objdump: -h --wide
+#xfail: rx-*-*
+# Test that lma is aligned when lma_region!=region and requested by script.
+
+#...
+.* 0+10000 +0+20000 .*
+.* 0+10100 +0+20100 .*
diff --git a/ld/testsuite/ld-scripts/rgn-at8.t b/ld/testsuite/ld-scripts/rgn-at8.t
new file mode 100644
index 0000000..e8aa1c7
--- /dev/null
+++ b/ld/testsuite/ld-scripts/rgn-at8.t
@@ -0,0 +1,12 @@
+MEMORY
+{
+ ram : ORIGIN = 0x10000, LENGTH = 0x10000
+ rom : ORIGIN = 0x20000, LENGTH = 0x10000
+}
+
+SECTIONS
+{
+ .text : ALIGN_WITH_INPUT {*(.text)} > ram AT> rom
+ .data : ALIGN_WITH_INPUT {*(.data)} > ram AT> rom
+ /DISCARD/ : {*(*)}
+}
diff --git a/ld/testsuite/ld-scripts/script.exp b/ld/testsuite/ld-scripts/script.exp
index 267c0be..792c7d0 100644
--- a/ld/testsuite/ld-scripts/script.exp
+++ b/ld/testsuite/ld-scripts/script.exp
@@ -137,3 +137,11 @@ foreach test_script $test_script_list {
xpass "REGION_ALIAS: $testname"
}
}
+
+set testname "ALIGN_WITH_INPUT"
+
+if ![ld_simple_link $ld tmpdir/script "$flags -T $srcdir/$subdir/align-with-input.t tmpdir/script.o"] {
+ xfail $testname
+} else {
+ xpass $testname
+}
--
1.7.7