summaryrefslogtreecommitdiff
blob: c0b1c13cdaffad0afba1a5e2e8a7db1e161be0ea (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
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
2002-11-22  Jakub Jelinek  <jakub@redhat.com>

	* ldgram.y (sect_constraint): New.
	(ONLY_IF_RO, ONLY_IF_RW): New tokens.
	(section): Add sect_constraint.  Pass additional argument
	to lang_enter_output_section_statement.
	* mri.c (mri_draw_tree): Pass additional argument to
	lang_enter_output_section_statement.
	* emultempl/pe.em (place_orphan): Likewise.
	(output_prev_sec_find): Disregard output section statements with
	constraint == -1.
	* emultempl/mmo.em (output_prev_sec_find): Likewise.
	(mmo_place_orphan): Pass additional argument to
	lang_enter_output_section_statement.
	* emultempl/elf32.em (output_prev_sec_find): Disregard output section
	statements with constraint == -1.
	(place_orphan): Pass additional argument to
	lang_enter_output_section_statement.
	* ldlang.c (lang_enter_overlay_section): Likewise.
	(lang_output_section_find_1): New.
	(lang_output_section_find): Use it.
	(lang_output_section_statement_lookup_1): New.
	(lang_output_section_statement_lookup): Use it.
	(check_section_callback, check_input_sections): New.
	(map_input_to_output_sections): Check if all input sections
	are readonly if ONLY_IF_RO or ONLY_IF_RW was seen.
	(strip_excluded_output_sections): Disregard output section statements
	with constraint == -1.
	(lang_record_phdrs): Likewise.
	(lang_enter_output_section_statement): Add constraint argument.
	Use lang_output_section_statement_lookup_1.
	* ldlang.h (lang_output_section_statement_type): Add constraint
	and all_input_readonly fields.
	(lang_enter_output_section_statement): Adjust prototype.
	* ldlex.l (ONLY_IF_RO, ONLY_IF_RW): New tokens.
	* scripttempl/elf.sc (.eh_frame, .gcc_except_table): Move into text
	segment if all input sections are readonly.

--- ld/emultempl/mmo.em.jj	Wed Jul 23 11:08:12 2003
+++ ld/emultempl/mmo.em	Fri Sep 19 17:30:02 2003
@@ -47,6 +47,8 @@ output_prev_sec_find (lang_output_sectio
        u = lookup->next)
     {
       lookup = &u->output_section_statement;
+      if (lookup->constraint == -1)
+	continue;
       if (lookup == os)
 	break;
       if (lookup->bfd_section != NULL
@@ -130,7 +132,7 @@ mmo_place_orphan (lang_input_statement_t
 					    (bfd_vma) 0,
 					    (etree_type *) NULL,
 					    (etree_type *) NULL,
-					    (etree_type *) NULL);
+					    (etree_type *) NULL, 0);
 
   lang_add_section (&os->children, s, os, file);
 
--- ld/emultempl/pe.em.jj	Thu Aug 21 11:28:48 2003
+++ ld/emultempl/pe.em	Fri Sep 19 17:30:02 2003
@@ -1453,6 +1453,8 @@ output_prev_sec_find (lang_output_sectio
        u = lookup->next)
     {
       lookup = &u->output_section_statement;
+      if (lookup->constraint == -1)
+	continue;
       if (lookup == os)
 	return s;
 
@@ -1617,7 +1619,7 @@ gld_${EMULATION_NAME}_place_orphan (lang
 						(bfd_vma) 0,
 						(etree_type *) NULL,
 						(etree_type *) NULL,
-						(etree_type *) NULL);
+						(etree_type *) NULL, 0);
 
       lang_add_section (&add_child, s, os, file);
 
--- ld/emultempl/elf32.em.jj	Thu Aug 21 11:28:48 2003
+++ ld/emultempl/elf32.em	Fri Sep 19 17:30:02 2003
@@ -1016,7 +1016,8 @@ output_rel_find (asection *sec, int isdy
   for (u = lang_output_section_statement.head; u; u = lookup->next)
     {
       lookup = &u->output_section_statement;
-      if (strncmp (".rel", lookup->name, 4) == 0)
+      if (lookup->constraint != -1
+	  && strncmp (".rel", lookup->name, 4) == 0)
 	{
 	  int lookrela = lookup->name[4] == 'a';
 
@@ -1264,7 +1265,7 @@ gld${EMULATION_NAME}_place_orphan (lang_
 					    (bfd_vma) 0,
 					    (etree_type *) NULL,
 					    (etree_type *) NULL,
-					    load_base);
+					    load_base, 0);
 
   lang_add_section (&os->children, s, os, file);
 
--- ld/scripttempl/elf.sc.jj	Wed Jul 23 11:08:12 2003
+++ ld/scripttempl/elf.sc	Fri Sep 19 17:30:02 2003
@@ -283,6 +283,8 @@ cat <<EOF
   ${CREATE_SHLIB-${SBSS2}}
   ${OTHER_READONLY_SECTIONS}
   .eh_frame_hdr : { *(.eh_frame_hdr) }
+  .eh_frame     ${RELOCATING-0} : ONLY_IF_RO { KEEP (*(.eh_frame)) }
+  .gcc_except_table ${RELOCATING-0} : ONLY_IF_RO { *(.gcc_except_table) }
 
   /* Adjust the address for the data segment.  We want to adjust up to
      the same address within the page on the next page up.  */
@@ -316,8 +318,8 @@ cat <<EOF
   .data1        ${RELOCATING-0} : { *(.data1) }
   .tdata	${RELOCATING-0} : { *(.tdata${RELOCATING+ .tdata.* .gnu.linkonce.td.*}) }
   .tbss		${RELOCATING-0} : { *(.tbss${RELOCATING+ .tbss.* .gnu.linkonce.tb.*})${RELOCATING+ *(.tcommon)} }
-  .eh_frame     ${RELOCATING-0} : { KEEP (*(.eh_frame)) }
-  .gcc_except_table ${RELOCATING-0} : { *(.gcc_except_table) }
+  .eh_frame     ${RELOCATING-0} : ONLY_IF_RW { KEEP (*(.eh_frame)) }
+  .gcc_except_table ${RELOCATING-0} : ONLY_IF_RW { *(.gcc_except_table) }
   ${WRITABLE_RODATA+${RODATA}}
   ${OTHER_READWRITE_SECTIONS}
   ${TEXT_DYNAMIC-${DYNAMIC}}
--- ld/ldgram.y.jj	Thu Aug 21 11:28:48 2003
+++ ld/ldgram.y	Fri Sep 19 17:38:10 2003
@@ -143,14 +143,14 @@ static int error_index;
 %token ORIGIN FILL
 %token LENGTH CREATE_OBJECT_SYMBOLS INPUT GROUP OUTPUT CONSTRUCTORS
 %token ALIGNMOD AT SUBALIGN PROVIDE
-%type <token> assign_op atype attributes_opt
+%type <token> assign_op atype attributes_opt sect_constraint
 %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
+%token KEEP ONLY_IF_RO ONLY_IF_RW
 %token EXCLUDE_FILE
 %type <versyms> vers_defns
 %type <versnode> vers_tag
@@ -833,22 +833,29 @@ opt_subalign:
 	|	{ $$ = 0; }
 	;
 
+sect_constraint:
+		ONLY_IF_RO { $$ = ONLY_IF_RO; }
+	|	ONLY_IF_RW { $$ = ONLY_IF_RW; }
+	|	{ $$ = 0; }
+	;
+
 section:	NAME 		{ ldlex_expression(); }
 		opt_exp_with_type
 		opt_at
 		opt_subalign	{ ldlex_popstate (); ldlex_script (); }
+		sect_constraint
 		'{'
 			{
 			  lang_enter_output_section_statement($1, $3,
 							      sectype,
-							      0, 0, $5, $4);
+							      0, 0, $5, $4, $7);
 			}
 		statement_list_opt
  		'}' { ldlex_popstate (); ldlex_expression (); }
 		memspec_opt memspec_at_opt phdr_opt fill_opt
 		{
 		  ldlex_popstate ();
-		  lang_leave_output_section_statement ($15, $12, $14, $13);
+		  lang_leave_output_section_statement ($16, $13, $15, $14);
 		}
 		opt_comma
 		{}
--- ld/mri.c.jj	Wed Jul 23 11:08:12 2003
+++ ld/mri.c	Fri Sep 19 17:30:02 2003
@@ -220,7 +220,7 @@ mri_draw_tree (void)
 
 	  lang_enter_output_section_statement (p->name, base,
 					       p->ok_to_load ? 0 : noload_section,
-					       1, align, subalign, NULL);
+					       1, align, subalign, NULL, 0);
 	  base = 0;
 	  tmp = xmalloc (sizeof *tmp);
 	  tmp->next = NULL;
--- ld/ldlang.h.jj	Thu Aug 21 11:28:48 2003
+++ ld/ldlang.h	Fri Sep 19 17:30:02 2003
@@ -132,6 +132,8 @@ typedef struct lang_output_section_state
 
   int subsection_alignment;	/* alignment of components */
   int section_alignment;	/* alignment of start of section */
+  int constraint;
+  bfd_boolean all_input_readonly;
 
   union etree_union *load_base;
 
@@ -394,7 +396,7 @@ extern lang_output_section_statement_typ
    bfd_vma block_value,
    etree_type *align,
    etree_type *subalign,
-   etree_type *);
+   etree_type *, int);
 extern void lang_final
   (void);
 extern void lang_process
--- ld/ldlang.c.jj	Thu Aug 21 11:28:48 2003
+++ ld/ldlang.c	Fri Sep 19 17:40:21 2003
@@ -562,7 +562,7 @@ lang_memory_default (asection *section)
 }
 
 lang_output_section_statement_type *
-lang_output_section_find (const char *const name)
+lang_output_section_find_1 (const char *const name, int constraint)
 {
   lang_statement_union_type *u;
   lang_output_section_statement_type *lookup;
@@ -570,18 +570,26 @@ lang_output_section_find (const char *co
   for (u = lang_output_section_statement.head; u != NULL; u = lookup->next)
     {
       lookup = &u->output_section_statement;
-      if (strcmp (name, lookup->name) == 0)
+      if (strcmp (name, lookup->name) == 0
+	  && lookup->constraint != -1
+	  && (constraint == 0 || constraint == lookup->constraint))
 	return lookup;
     }
   return NULL;
 }
 
 lang_output_section_statement_type *
-lang_output_section_statement_lookup (const char *const name)
+lang_output_section_find (const char *const name)
+{
+  return lang_output_section_find_1 (name, 0);
+}
+
+lang_output_section_statement_type *
+lang_output_section_statement_lookup_1 (const char *const name, int constraint)
 {
   lang_output_section_statement_type *lookup;
 
-  lookup = lang_output_section_find (name);
+  lookup = lang_output_section_find_1 (name, constraint);
   if (lookup == NULL)
     {
       lookup = new_stat (lang_output_section_statement, stat_ptr);
@@ -594,6 +602,7 @@ lang_output_section_statement_lookup (co
       lookup->next = NULL;
       lookup->bfd_section = NULL;
       lookup->processed = FALSE;
+      lookup->constraint = constraint;
       lookup->sectype = normal_section;
       lookup->addr_tree = NULL;
       lang_list_init (&lookup->children);
@@ -613,6 +622,12 @@ lang_output_section_statement_lookup (co
   return lookup;
 }
 
+lang_output_section_statement_type *
+lang_output_section_statement_lookup (const char *const name)
+{
+  return lang_output_section_statement_lookup_1 (name, 0);
+}
+
 static void
 lang_map_flags (flagword flag)
 {
@@ -1278,6 +1293,30 @@ output_section_callback (lang_wild_state
     }
 }
 
+/* Check if all sections in a wild statement for a particular FILE
+   are readonly.  */
+
+static void
+check_section_callback (lang_wild_statement_type *ptr ATTRIBUTE_UNUSED,
+			struct wildcard_list *sec ATTRIBUTE_UNUSED,
+			asection *section,
+			lang_input_statement_type *file ATTRIBUTE_UNUSED,
+			void *output)
+{
+  /* Exclude sections that match UNIQUE_SECTION_LIST.  */
+  if (unique_section_p (bfd_get_section_name (file->the_bfd, section)))
+    return;
+
+  if (section->output_section == NULL)
+    {
+      flagword flags = bfd_get_section_flags (section->owner, section);
+
+      if ((flags & SEC_READONLY) == 0)
+	((lang_output_section_statement_type *) output)->all_input_readonly
+	  = FALSE;
+    }
+}
+
 /* This is passed a file name which must have been seen already and
    added to the statement tree.  We will see if it has been opened
    already and had its symbols read.  If not then we'll read it.  */
@@ -1923,6 +1962,40 @@ lang_place_undefineds (void)
     insert_undefined (ptr->name);
 }
 
+/* Check for all readonly or some readwrite sections.  */
+
+static void
+check_input_sections (lang_statement_union_type *s,
+		      lang_output_section_statement_type *output_section_statement)
+{
+  for (; s != (lang_statement_union_type *) NULL; s = s->header.next)
+    {
+      switch (s->header.type)
+      {
+      case lang_wild_statement_enum:
+	walk_wild (&s->wild_statement, check_section_callback,
+		   output_section_statement);
+	if (! output_section_statement->all_input_readonly)
+	  return;
+	break;
+      case lang_constructors_statement_enum:
+	check_input_sections (constructor_list.head,
+			      output_section_statement);
+	if (! output_section_statement->all_input_readonly)
+	  return;
+	break;
+      case lang_group_statement_enum:
+	check_input_sections (s->group_statement.children.head,
+			      output_section_statement);
+	if (! output_section_statement->all_input_readonly)
+	  return;
+	break;
+      default:
+	break;
+      }
+    }
+}
+
 /* Open input files and attach to output sections.  */
 
 static void
@@ -1943,6 +2016,23 @@ map_input_to_output_sections
 					output_section_statement);
 	  break;
 	case lang_output_section_statement_enum:
+	  if (s->output_section_statement.constraint)
+	    {
+	      if (s->output_section_statement.constraint == -1)
+		break;
+	      s->output_section_statement.all_input_readonly = TRUE;
+	      check_input_sections (s->output_section_statement.children.head,
+				    &s->output_section_statement);
+	      if ((s->output_section_statement.all_input_readonly
+		   && s->output_section_statement.constraint == ONLY_IF_RW)
+		  || (!s->output_section_statement.all_input_readonly
+		      && s->output_section_statement.constraint == ONLY_IF_RO))
+		{
+		  s->output_section_statement.constraint = -1;
+		  break;
+		}
+	    }
+
 	  map_input_to_output_sections (s->output_section_statement.children.head,
 					target,
 					&s->output_section_statement);
@@ -2013,6 +2103,8 @@ strip_excluded_output_sections (void)
       asection *s;
 
       os = &u->output_section_statement;
+      if (os->constraint == -1)
+	continue;
       s = os->bfd_section;
       if (s != NULL && (s->flags & SEC_EXCLUDE) != 0)
 	{
@@ -3857,13 +3949,15 @@ lang_enter_output_section_statement (con
 				     bfd_vma block_value,
 				     etree_type *align,
 				     etree_type *subalign,
-				     etree_type *ebase)
+				     etree_type *ebase,
+				     int constraint)
 {
   lang_output_section_statement_type *os;
 
   current_section =
    os =
-    lang_output_section_statement_lookup (output_section_statement_name);
+    lang_output_section_statement_lookup_1 (output_section_statement_name,
+					    constraint);
 
   /* Add this statement to tree.  */
 #if 0
@@ -4558,6 +4652,8 @@ lang_record_phdrs (void)
 	  struct lang_output_section_phdr_list *pl;
 
 	  os = &u->output_section_statement;
+	  if (os->constraint == -1)
+	    continue;
 
 	  pl = os->phdrs;
 	  if (pl != NULL)
@@ -4617,7 +4713,8 @@ lang_record_phdrs (void)
     {
       struct lang_output_section_phdr_list *pl;
 
-      if (u->output_section_statement.bfd_section == NULL)
+      if (u->output_section_statement.constraint == -1
+	  || u->output_section_statement.bfd_section == NULL)
 	continue;
 
       for (pl = u->output_section_statement.phdrs;
@@ -4689,7 +4786,7 @@ lang_enter_overlay_section (const char *
   etree_type *size;
 
   lang_enter_output_section_statement (name, overlay_vma, normal_section,
-				       0, 0, overlay_subalign, 0);
+				       0, 0, overlay_subalign, 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
--- ld/ldlex.l.jj	Thu Aug 21 11:28:48 2003
+++ ld/ldlex.l	Fri Sep 19 17:30:02 2003
@@ -299,6 +299,8 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^]([*?
 <EXPRESSION,BOTH,SCRIPT>"COPY"		{ RTOKEN(COPY);}
 <EXPRESSION,BOTH,SCRIPT>"INFO"		{ RTOKEN(INFO);}
 <EXPRESSION,BOTH,SCRIPT>"OVERLAY"	{ RTOKEN(OVERLAY);}
+<EXPRESSION,BOTH,SCRIPT>"ONLY_IF_RO"	{ RTOKEN(ONLY_IF_RO); }
+<EXPRESSION,BOTH,SCRIPT>"ONLY_IF_RW"	{ RTOKEN(ONLY_IF_RW); }
 <BOTH,SCRIPT>"o"			{ RTOKEN(ORIGIN);}
 <BOTH,SCRIPT>"org"			{ RTOKEN(ORIGIN);}
 <BOTH,SCRIPT>"l"			{ RTOKEN( LENGTH);}