c006c94af632aba5aa7ffb155b2c27f601dc95c7
[openwrt/staging/robimarko.git] /
1 From 3d9c8f6b3f033a6092425b7344647fb51dbed5c6 Mon Sep 17 00:00:00 2001
2 From: Alan Modra <amodra@gmail.com>
3 Date: Sun, 26 Aug 2018 14:23:38 +0930
4 Subject: [PATCH] Delay evaluation of alignment expressions in output sections
5
6 git commit 702d16713 broke expressions using CONSTANT(COMMONPAGESIZE)
7 in ALIGN or SUBALIGN of output section statements, because these
8 optional fields were evaluated at script parse time and the patch in
9 question delayed setting of config.commonpagesize. The right thing to
10 do is keep the tree representation of those fields for later
11 evaluation.
12
13 PR 23571
14 * ldlang.h (section_alignment): Make it an expression tree.
15 (subsection_alignment): Likewise.
16 * ldlang.c (topower): Delete.
17 (output_section_statement_newfunc): Adjust initialization.
18 (init_os): Evaluate section_alignment.
19 (lang_size_sections_1): Likewise.
20 (size_input_section): Evaluate subsection_alignment.
21 (lang_enter_output_section_statement): Don't evaluate here.
22 (lang_new_phdr): Use exp_get_vma rather than exp_get_value_int.
23 * ldexp.h (exp_get_value_int): Delete.
24 (exp_get_power): Declare.
25 * ldexp.c (exp_get_value_int): Delete.
26 (exp_get_power): New function.
27 * emultempl/pe.em (place_orphan): Build expression for section
28 alignment.
29 * emultempl/pep.em (place_orphan): Likewise.
30 * testsuite/ld-scripts/pr23571.d,
31 * testsuite/ld-scripts/pr23571.t: New test.
32 * testsuite/ld-scripts/align.exp: Run it.
33 ---
34 ld/ChangeLog | 23 +++++++++++++++++++
35 ld/emultempl/pe.em | 2 +-
36 ld/emultempl/pep.em | 2 +-
37 ld/ldexp.c | 20 ++++++++++++++--
38 ld/ldexp.h | 4 ++--
39 ld/ldlang.c | 48 +++++++++++++--------------------------
40 ld/ldlang.h | 4 ++--
41 ld/testsuite/ld-scripts/align.exp | 4 ++++
42 ld/testsuite/ld-scripts/pr23571.d | 10 ++++++++
43 ld/testsuite/ld-scripts/pr23571.t | 11 +++++++++
44 10 files changed, 88 insertions(+), 40 deletions(-)
45 create mode 100644 ld/testsuite/ld-scripts/pr23571.d
46 create mode 100644 ld/testsuite/ld-scripts/pr23571.t
47
48 --- a/ld/emultempl/pe.em
49 +++ b/ld/emultempl/pe.em
50 @@ -2165,7 +2165,7 @@ gld_${EMULATION_NAME}_place_orphan (asec
51 &add_child);
52 if (bfd_link_relocatable (&link_info))
53 {
54 - os->section_alignment = s->alignment_power;
55 + os->section_alignment = exp_intop (1U << s->alignment_power);
56 os->bfd_section->alignment_power = s->alignment_power;
57 }
58 }
59 --- a/ld/emultempl/pep.em
60 +++ b/ld/emultempl/pep.em
61 @@ -1962,7 +1962,7 @@ gld_${EMULATION_NAME}_place_orphan (asec
62 &add_child);
63 if (bfd_link_relocatable (&link_info))
64 {
65 - os->section_alignment = s->alignment_power;
66 + os->section_alignment = exp_intop (1U << s->alignment_power);
67 os->bfd_section->alignment_power = s->alignment_power;
68 }
69 }
70 --- a/ld/ldexp.c
71 +++ b/ld/ldexp.c
72 @@ -1522,10 +1522,26 @@ exp_get_vma (etree_type *tree, bfd_vma d
73 return def;
74 }
75
76 +/* Return the smallest non-negative integer such that two raised to
77 + that power is at least as large as the vma evaluated at TREE, if
78 + TREE is a non-NULL expression that can be resolved. If TREE is
79 + NULL or cannot be resolved, return -1. */
80 +
81 int
82 -exp_get_value_int (etree_type *tree, int def, char *name)
83 +exp_get_power (etree_type *tree, char *name)
84 {
85 - return exp_get_vma (tree, def, name);
86 + bfd_vma x = exp_get_vma (tree, -1, name);
87 + bfd_vma p2;
88 + int n;
89 +
90 + if (x == (bfd_vma) -1)
91 + return -1;
92 +
93 + for (n = 0, p2 = 1; p2 < x; ++n, p2 <<= 1)
94 + if (p2 == 0)
95 + break;
96 +
97 + return n;
98 }
99
100 fill_type *
101 --- a/ld/ldexp.h
102 +++ b/ld/ldexp.h
103 @@ -229,8 +229,8 @@ void exp_print_tree
104 (etree_type *);
105 bfd_vma exp_get_vma
106 (etree_type *, bfd_vma, char *);
107 -int exp_get_value_int
108 - (etree_type *, int, char *);
109 +int exp_get_power
110 + (etree_type *, char *);
111 fill_type *exp_get_fill
112 (etree_type *, fill_type *, char *);
113 bfd_vma exp_get_abs_int
114 --- a/ld/ldlang.c
115 +++ b/ld/ldlang.c
116 @@ -1199,8 +1199,8 @@ output_section_statement_newfunc (struct
117 ret = (struct out_section_hash_entry *) entry;
118 memset (&ret->s, 0, sizeof (ret->s));
119 ret->s.header.type = lang_output_section_statement_enum;
120 - ret->s.output_section_statement.subsection_alignment = -1;
121 - ret->s.output_section_statement.section_alignment = -1;
122 + ret->s.output_section_statement.subsection_alignment = NULL;
123 + ret->s.output_section_statement.section_alignment = NULL;
124 ret->s.output_section_statement.block_value = 1;
125 lang_list_init (&ret->s.output_section_statement.children);
126 lang_statement_append (stat_ptr, &ret->s, &ret->s.header.next);
127 @@ -2193,8 +2193,9 @@ init_os (lang_output_section_statement_t
128 exp_init_os (s->load_base);
129
130 /* If supplied an alignment, set it. */
131 - if (s->section_alignment != -1)
132 - s->bfd_section->alignment_power = s->section_alignment;
133 + if (s->section_alignment != NULL)
134 + s->bfd_section->alignment_power = exp_get_power (s->section_alignment,
135 + "section alignment");
136 }
137
138 /* Make sure that all output sections mentioned in an expression are
139 @@ -4706,8 +4707,10 @@ size_input_section
140 is greater than any seen before, then record it too. Perform
141 the alignment by inserting a magic 'padding' statement. */
142
143 - if (output_section_statement->subsection_alignment != -1)
144 - i->alignment_power = output_section_statement->subsection_alignment;
145 + if (output_section_statement->subsection_alignment != NULL)
146 + i->alignment_power
147 + = exp_get_power (output_section_statement->subsection_alignment,
148 + "subsection alignment");
149
150 if (o->alignment_power < i->alignment_power)
151 o->alignment_power = i->alignment_power;
152 @@ -5147,7 +5150,8 @@ lang_size_sections_1
153 section_alignment = os->bfd_section->alignment_power;
154 }
155 else
156 - section_alignment = os->section_alignment;
157 + section_alignment = exp_get_power (os->section_alignment,
158 + "section alignment");
159
160 /* Align to what the section needs. */
161 if (section_alignment > 0)
162 @@ -5225,7 +5229,8 @@ lang_size_sections_1
163 only align according to the value in the output
164 statement. */
165 if (os->lma_region != os->region)
166 - section_alignment = os->section_alignment;
167 + section_alignment = exp_get_power (os->section_alignment,
168 + "section alignment");
169 if (section_alignment > 0)
170 lma = align_power (lma, section_alignment);
171 }
172 @@ -6673,25 +6678,6 @@ lang_add_output (const char *name, int f
173 }
174 }
175
176 -static int
177 -topower (int x)
178 -{
179 - unsigned int i = 1;
180 - int l;
181 -
182 - if (x < 0)
183 - return -1;
184 -
185 - for (l = 0; l < 32; l++)
186 - {
187 - if (i >= (unsigned int) x)
188 - return l;
189 - i <<= 1;
190 - }
191 -
192 - return 0;
193 -}
194 -
195 lang_output_section_statement_type *
196 lang_enter_output_section_statement (const char *output_section_statement_name,
197 etree_type *address_exp,
198 @@ -6727,10 +6713,8 @@ lang_enter_output_section_statement (con
199 einfo (_("%F%P:%pS: error: align with input and explicit align specified\n"),
200 NULL);
201
202 - os->subsection_alignment =
203 - topower (exp_get_value_int (subalign, -1, "subsection alignment"));
204 - os->section_alignment =
205 - topower (exp_get_value_int (align, -1, "section alignment"));
206 + os->subsection_alignment = subalign;
207 + os->section_alignment = align;
208
209 os->load_base = ebase;
210 return os;
211 @@ -7748,7 +7732,7 @@ lang_new_phdr (const char *name,
212 n = (struct lang_phdr *) stat_alloc (sizeof (struct lang_phdr));
213 n->next = NULL;
214 n->name = name;
215 - n->type = exp_get_value_int (type, 0, "program header type");
216 + n->type = exp_get_vma (type, 0, "program header type");
217 n->filehdr = filehdr;
218 n->phdrs = phdrs;
219 n->at = at;
220 --- a/ld/ldlang.h
221 +++ b/ld/ldlang.h
222 @@ -143,6 +143,8 @@ typedef struct lang_output_section_state
223 fill_type *fill;
224 union etree_union *addr_tree;
225 union etree_union *load_base;
226 + union etree_union *section_alignment;
227 + union etree_union *subsection_alignment;
228
229 /* If non-null, an expression to evaluate after setting the section's
230 size. The expression is evaluated inside REGION (above) with '.'
231 @@ -153,8 +155,6 @@ typedef struct lang_output_section_state
232 lang_output_section_phdr_list *phdrs;
233
234 unsigned int block_value;
235 - int subsection_alignment; /* Alignment of components. */
236 - int section_alignment; /* Alignment of start of section. */
237 int constraint;
238 flagword flags;
239 enum section_type sectype;
240 --- a/ld/testsuite/ld-scripts/align.exp
241 +++ b/ld/testsuite/ld-scripts/align.exp
242 @@ -53,3 +53,7 @@ if ![is_aout_format] {
243 }
244 run_dump_test align2c
245 set LDFLAGS "$saved_LDFLAGS"
246 +
247 +if { [is_elf_format] && ![is_generic_elf] } {
248 + run_dump_test pr23571
249 +}
250 --- /dev/null
251 +++ b/ld/testsuite/ld-scripts/pr23571.d
252 @@ -0,0 +1,10 @@
253 +#source: align2a.s
254 +#ld: -T pr23571.t -z common-page-size=0x1000
255 +#objdump: -h -w
256 +
257 +.*: +file format .*
258 +
259 +Sections:
260 +Idx Name +Size +VMA +LMA +File off +Algn +Flags
261 + +0 \.text +[0-9a-f]* +0+1000 +0+1000 .*
262 + +1 \.data +[0-9a-f]* +0+2000 +0+2000 +[0-9a-f]* +2\*\*12 .*
263 --- /dev/null
264 +++ b/ld/testsuite/ld-scripts/pr23571.t
265 @@ -0,0 +1,11 @@
266 +SECTIONS
267 +{
268 + .text CONSTANT(COMMONPAGESIZE) : {
269 + *(.text)
270 + }
271 +
272 + .data : ALIGN(CONSTANT(COMMONPAGESIZE)) {
273 + *(.data)
274 + }
275 + /DISCARD/ : {*(*)}
276 +}