aboutsummaryrefslogtreecommitdiffstats
path: root/toolchain/binutils/patches/2.31.1/100-delay_evaluation_of_alignment_expressions_in_output_sections.patch
blob: c006c94af632aba5aa7ffb155b2c27f601dc95c7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
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/ : {*(*)}
+}