-
-
Notifications
You must be signed in to change notification settings - Fork 154
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
284 additions
and
8 deletions.
There are no files selected for viewing
276 changes: 276 additions & 0 deletions
276
...ils/patches/2.31.1/100-delay_evaluation_of_alignment_expressions_in_output_sections.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,276 @@ | |||
From 3d9c8f6b3f033a6092425b7344647fb51dbed5c6 Mon Sep 17 00:00:00 2001 | |||
From: Alan Modra <amodra@gmail.com> | |||
Date: Sun, 26 Aug 2018 14:23:38 +0930 | |||
Subject: [PATCH] Delay evaluation of alignment expressions in output sections | |||
|
|||
git commit 702d16713 broke expressions using CONSTANT(COMMONPAGESIZE) | |||
in ALIGN or SUBALIGN of output section statements, because these | |||
optional fields were evaluated at script parse time and the patch in | |||
question delayed setting of config.commonpagesize. The right thing to | |||
do is keep the tree representation of those fields for later | |||
evaluation. | |||
|
|||
PR 23571 | |||
* ldlang.h (section_alignment): Make it an expression tree. | |||
(subsection_alignment): Likewise. | |||
* ldlang.c (topower): Delete. | |||
(output_section_statement_newfunc): Adjust initialization. | |||
(init_os): Evaluate section_alignment. | |||
(lang_size_sections_1): Likewise. | |||
(size_input_section): Evaluate subsection_alignment. | |||
(lang_enter_output_section_statement): Don't evaluate here. | |||
(lang_new_phdr): Use exp_get_vma rather than exp_get_value_int. | |||
* ldexp.h (exp_get_value_int): Delete. | |||
(exp_get_power): Declare. | |||
* ldexp.c (exp_get_value_int): Delete. | |||
(exp_get_power): New function. | |||
* emultempl/pe.em (place_orphan): Build expression for section | |||
alignment. | |||
* emultempl/pep.em (place_orphan): Likewise. | |||
* testsuite/ld-scripts/pr23571.d, | |||
* testsuite/ld-scripts/pr23571.t: New test. | |||
* testsuite/ld-scripts/align.exp: Run it. | |||
--- | |||
ld/ChangeLog | 23 +++++++++++++++++++ | |||
ld/emultempl/pe.em | 2 +- | |||
ld/emultempl/pep.em | 2 +- | |||
ld/ldexp.c | 20 ++++++++++++++-- | |||
ld/ldexp.h | 4 ++-- | |||
ld/ldlang.c | 48 +++++++++++++-------------------------- | |||
ld/ldlang.h | 4 ++-- | |||
ld/testsuite/ld-scripts/align.exp | 4 ++++ | |||
ld/testsuite/ld-scripts/pr23571.d | 10 ++++++++ | |||
ld/testsuite/ld-scripts/pr23571.t | 11 +++++++++ | |||
10 files changed, 88 insertions(+), 40 deletions(-) | |||
create mode 100644 ld/testsuite/ld-scripts/pr23571.d | |||
create mode 100644 ld/testsuite/ld-scripts/pr23571.t | |||
|
|||
--- a/ld/emultempl/pe.em | |||
+++ b/ld/emultempl/pe.em | |||
@@ -2165,7 +2165,7 @@ gld_${EMULATION_NAME}_place_orphan (asec | |||
&add_child); | |||
if (bfd_link_relocatable (&link_info)) | |||
{ | |||
- os->section_alignment = s->alignment_power; | |||
+ os->section_alignment = exp_intop (1U << s->alignment_power); | |||
os->bfd_section->alignment_power = s->alignment_power; | |||
} | |||
} | |||
--- a/ld/emultempl/pep.em | |||
+++ b/ld/emultempl/pep.em | |||
@@ -1962,7 +1962,7 @@ gld_${EMULATION_NAME}_place_orphan (asec | |||
&add_child); | |||
if (bfd_link_relocatable (&link_info)) | |||
{ | |||
- os->section_alignment = s->alignment_power; | |||
+ os->section_alignment = exp_intop (1U << s->alignment_power); | |||
os->bfd_section->alignment_power = s->alignment_power; | |||
} | |||
} | |||
--- a/ld/ldexp.c | |||
+++ b/ld/ldexp.c | |||
@@ -1522,10 +1522,26 @@ exp_get_vma (etree_type *tree, bfd_vma d | |||
return def; | |||
} | |||
|
|||
+/* Return the smallest non-negative integer such that two raised to | |||
+ that power is at least as large as the vma evaluated at TREE, if | |||
+ TREE is a non-NULL expression that can be resolved. If TREE is | |||
+ NULL or cannot be resolved, return -1. */ | |||
+ | |||
int | |||
-exp_get_value_int (etree_type *tree, int def, char *name) | |||
+exp_get_power (etree_type *tree, char *name) | |||
{ | |||
- return exp_get_vma (tree, def, name); | |||
+ bfd_vma x = exp_get_vma (tree, -1, name); | |||
+ bfd_vma p2; | |||
+ int n; | |||
+ | |||
+ if (x == (bfd_vma) -1) | |||
+ return -1; | |||
+ | |||
+ for (n = 0, p2 = 1; p2 < x; ++n, p2 <<= 1) | |||
+ if (p2 == 0) | |||
+ break; | |||
+ | |||
+ return n; | |||
} | |||
|
|||
fill_type * | |||
--- a/ld/ldexp.h | |||
+++ b/ld/ldexp.h | |||
@@ -229,8 +229,8 @@ void exp_print_tree | |||
(etree_type *); | |||
bfd_vma exp_get_vma | |||
(etree_type *, bfd_vma, char *); | |||
-int exp_get_value_int | |||
- (etree_type *, int, char *); | |||
+int exp_get_power | |||
+ (etree_type *, char *); | |||
fill_type *exp_get_fill | |||
(etree_type *, fill_type *, char *); | |||
bfd_vma exp_get_abs_int | |||
--- a/ld/ldlang.c | |||
+++ b/ld/ldlang.c | |||
@@ -1199,8 +1199,8 @@ output_section_statement_newfunc (struct | |||
ret = (struct out_section_hash_entry *) entry; | |||
memset (&ret->s, 0, sizeof (ret->s)); | |||
ret->s.header.type = lang_output_section_statement_enum; | |||
- ret->s.output_section_statement.subsection_alignment = -1; | |||
- ret->s.output_section_statement.section_alignment = -1; | |||
+ ret->s.output_section_statement.subsection_alignment = NULL; | |||
+ ret->s.output_section_statement.section_alignment = NULL; | |||
ret->s.output_section_statement.block_value = 1; | |||
lang_list_init (&ret->s.output_section_statement.children); | |||
lang_statement_append (stat_ptr, &ret->s, &ret->s.header.next); | |||
@@ -2193,8 +2193,9 @@ init_os (lang_output_section_statement_t | |||
exp_init_os (s->load_base); | |||
|
|||
/* If supplied an alignment, set it. */ | |||
- if (s->section_alignment != -1) | |||
- s->bfd_section->alignment_power = s->section_alignment; | |||
+ if (s->section_alignment != NULL) | |||
+ s->bfd_section->alignment_power = exp_get_power (s->section_alignment, | |||
+ "section alignment"); | |||
} | |||
|
|||
/* Make sure that all output sections mentioned in an expression are | |||
@@ -4706,8 +4707,10 @@ size_input_section | |||
is greater than any seen before, then record it too. Perform | |||
the alignment by inserting a magic 'padding' statement. */ | |||
|
|||
- if (output_section_statement->subsection_alignment != -1) | |||
- i->alignment_power = output_section_statement->subsection_alignment; | |||
+ if (output_section_statement->subsection_alignment != NULL) | |||
+ i->alignment_power | |||
+ = exp_get_power (output_section_statement->subsection_alignment, | |||
+ "subsection alignment"); | |||
|
|||
if (o->alignment_power < i->alignment_power) | |||
o->alignment_power = i->alignment_power; | |||
@@ -5147,7 +5150,8 @@ lang_size_sections_1 | |||
section_alignment = os->bfd_section->alignment_power; | |||
} | |||
else | |||
- section_alignment = os->section_alignment; | |||
+ section_alignment = exp_get_power (os->section_alignment, | |||
+ "section alignment"); | |||
|
|||
/* Align to what the section needs. */ | |||
if (section_alignment > 0) | |||
@@ -5225,7 +5229,8 @@ lang_size_sections_1 | |||
only align according to the value in the output | |||
statement. */ | |||
if (os->lma_region != os->region) | |||
- section_alignment = os->section_alignment; | |||
+ section_alignment = exp_get_power (os->section_alignment, | |||
+ "section alignment"); | |||
if (section_alignment > 0) | |||
lma = align_power (lma, section_alignment); | |||
} | |||
@@ -6673,25 +6678,6 @@ lang_add_output (const char *name, int f | |||
} | |||
} | |||
|
|||
-static int | |||
-topower (int x) | |||
-{ | |||
- unsigned int i = 1; | |||
- int l; | |||
- | |||
- if (x < 0) | |||
- return -1; | |||
- | |||
- for (l = 0; l < 32; l++) | |||
- { | |||
- if (i >= (unsigned int) x) | |||
- return l; | |||
- i <<= 1; | |||
- } | |||
- | |||
- return 0; | |||
-} | |||
- | |||
lang_output_section_statement_type * | |||
lang_enter_output_section_statement (const char *output_section_statement_name, | |||
etree_type *address_exp, | |||
@@ -6727,10 +6713,8 @@ lang_enter_output_section_statement (con | |||
einfo (_("%F%P:%pS: 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 = | |||
- topower (exp_get_value_int (align, -1, "section alignment")); | |||
+ os->subsection_alignment = subalign; | |||
+ os->section_alignment = align; | |||
|
|||
os->load_base = ebase; | |||
return os; | |||
@@ -7748,7 +7732,7 @@ lang_new_phdr (const char *name, | |||
n = (struct lang_phdr *) stat_alloc (sizeof (struct lang_phdr)); | |||
n->next = NULL; | |||
n->name = name; | |||
- n->type = exp_get_value_int (type, 0, "program header type"); | |||
+ n->type = exp_get_vma (type, 0, "program header type"); | |||
n->filehdr = filehdr; | |||
n->phdrs = phdrs; | |||
n->at = at; | |||
--- a/ld/ldlang.h | |||
+++ b/ld/ldlang.h | |||
@@ -143,6 +143,8 @@ typedef struct lang_output_section_state | |||
fill_type *fill; | |||
union etree_union *addr_tree; | |||
union etree_union *load_base; | |||
+ union etree_union *section_alignment; | |||
+ union etree_union *subsection_alignment; | |||
|
|||
/* If non-null, an expression to evaluate after setting the section's | |||
size. The expression is evaluated inside REGION (above) with '.' | |||
@@ -153,8 +155,6 @@ typedef struct lang_output_section_state | |||
lang_output_section_phdr_list *phdrs; | |||
|
|||
unsigned int block_value; | |||
- int subsection_alignment; /* Alignment of components. */ | |||
- int section_alignment; /* Alignment of start of section. */ | |||
int constraint; | |||
flagword flags; | |||
enum section_type sectype; | |||
--- a/ld/testsuite/ld-scripts/align.exp | |||
+++ b/ld/testsuite/ld-scripts/align.exp | |||
@@ -53,3 +53,7 @@ if ![is_aout_format] { | |||
} | |||
run_dump_test align2c | |||
set LDFLAGS "$saved_LDFLAGS" | |||
+ | |||
+if { [is_elf_format] && ![is_generic_elf] } { | |||
+ run_dump_test pr23571 | |||
+} | |||
--- /dev/null | |||
+++ b/ld/testsuite/ld-scripts/pr23571.d | |||
@@ -0,0 +1,10 @@ | |||
+#source: align2a.s | |||
+#ld: -T pr23571.t -z common-page-size=0x1000 | |||
+#objdump: -h -w | |||
+ | |||
+.*: +file format .* | |||
+ | |||
+Sections: | |||
+Idx Name +Size +VMA +LMA +File off +Algn +Flags | |||
+ +0 \.text +[0-9a-f]* +0+1000 +0+1000 .* | |||
+ +1 \.data +[0-9a-f]* +0+2000 +0+2000 +[0-9a-f]* +2\*\*12 .* | |||
--- /dev/null | |||
+++ b/ld/testsuite/ld-scripts/pr23571.t | |||
@@ -0,0 +1,11 @@ | |||
+SECTIONS | |||
+{ | |||
+ .text CONSTANT(COMMONPAGESIZE) : { | |||
+ *(.text) | |||
+ } | |||
+ | |||
+ .data : ALIGN(CONSTANT(COMMONPAGESIZE)) { | |||
+ *(.data) | |||
+ } | |||
+ /DISCARD/ : {*(*)} | |||
+} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters