]>
Commit | Line | Data |
---|---|---|
252b5132 | 1 | /* mri.c -- handle MRI style linker scripts |
891fa266 NC |
2 | Copyright 1991, 92, 93, 94, 95, 96, 1997, 1998, 2000 |
3 | Free Software Foundation, Inc. | |
252b5132 RH |
4 | |
5 | This file is part of GLD, the Gnu Linker. | |
6 | ||
7 | GLD is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 2, or (at your option) | |
10 | any later version. | |
11 | ||
12 | GLD is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with GLD; see the file COPYING. If not, write to the Free | |
19 | Software Foundation, 59 Temple Place - Suite 330, Boston, MA | |
891fa266 | 20 | 02111-1307, USA. |
252b5132 | 21 | |
891fa266 NC |
22 | This bit does the tree decoration when MRI style link scripts |
23 | are parsed. | |
252b5132 | 24 | |
891fa266 | 25 | Contributed by Steve Chamberlain <sac@cygnus.com>. */ |
252b5132 RH |
26 | |
27 | #include "bfd.h" | |
5cc18311 | 28 | #include "sysdep.h" |
252b5132 RH |
29 | #include "ld.h" |
30 | #include "ldexp.h" | |
31 | #include "ldlang.h" | |
32 | #include "ldmisc.h" | |
33 | #include "mri.h" | |
34 | #include "ldgram.h" | |
35 | #include "libiberty.h" | |
36 | ||
891fa266 NC |
37 | struct section_name_struct |
38 | { | |
252b5132 RH |
39 | struct section_name_struct *next; |
40 | CONST char *name; | |
41 | CONST char *alias; | |
42 | etree_type *vma; | |
43 | etree_type *align; | |
44 | etree_type *subalign; | |
45 | int ok_to_load; | |
891fa266 | 46 | }; |
252b5132 RH |
47 | |
48 | unsigned int symbol_truncate = 10000; | |
49 | struct section_name_struct *order; | |
50 | struct section_name_struct *only_load; | |
51 | struct section_name_struct *address; | |
52 | struct section_name_struct *alias; | |
53 | ||
54 | struct section_name_struct *alignment; | |
55 | struct section_name_struct *subalignment; | |
56 | ||
57 | static struct section_name_struct **lookup | |
58 | PARAMS ((const char *name, struct section_name_struct **list)); | |
59 | static void mri_add_to_list PARAMS ((struct section_name_struct **list, | |
60 | const char *name, etree_type *vma, | |
61 | const char *zalias, etree_type *align, | |
62 | etree_type *subalign)); | |
63 | ||
64 | static struct section_name_struct ** | |
65 | lookup (name, list) | |
66 | CONST char *name; | |
67 | struct section_name_struct **list; | |
68 | { | |
252b5132 | 69 | struct section_name_struct **ptr = list; |
5cc18311 KH |
70 | |
71 | while (*ptr) | |
891fa266 NC |
72 | { |
73 | if (strcmp (name, (*ptr)->name) == 0) | |
74 | /* If this is a match, delete it, we only keep the last instance | |
75 | of any name. */ | |
76 | *ptr = (*ptr)->next; | |
77 | else | |
78 | ptr = &((*ptr)->next); | |
252b5132 | 79 | } |
252b5132 | 80 | |
891fa266 | 81 | *ptr = (struct section_name_struct *) xmalloc (sizeof (struct section_name_struct)); |
252b5132 RH |
82 | return ptr; |
83 | } | |
84 | ||
85 | static void | |
86 | mri_add_to_list (list, name, vma, zalias, align, subalign) | |
87 | struct section_name_struct **list; | |
88 | CONST char *name; | |
89 | etree_type *vma; | |
90 | CONST char *zalias; | |
91 | etree_type *align; | |
92 | etree_type *subalign; | |
93 | { | |
891fa266 | 94 | struct section_name_struct **ptr = lookup (name,list); |
5cc18311 | 95 | |
252b5132 RH |
96 | (*ptr)->name = name; |
97 | (*ptr)->vma = vma; | |
891fa266 | 98 | (*ptr)->next = (struct section_name_struct *) NULL; |
252b5132 RH |
99 | (*ptr)->ok_to_load = 0; |
100 | (*ptr)->alias = zalias; | |
101 | (*ptr)->align = align; | |
102 | (*ptr)->subalign = subalign; | |
103 | } | |
104 | ||
252b5132 RH |
105 | void |
106 | mri_output_section (name, vma) | |
107 | CONST char *name; | |
108 | etree_type *vma; | |
109 | { | |
891fa266 | 110 | mri_add_to_list (& address, name, vma, 0,0,0); |
252b5132 RH |
111 | } |
112 | ||
891fa266 NC |
113 | /* If any ABSOLUTE <name> are in the script, only load those files |
114 | marked thus. */ | |
252b5132 RH |
115 | |
116 | void | |
117 | mri_only_load (name) | |
118 | CONST char *name; | |
119 | { | |
891fa266 | 120 | mri_add_to_list (&only_load, name, 0, 0,0,0); |
252b5132 RH |
121 | } |
122 | ||
252b5132 RH |
123 | void |
124 | mri_base (exp) | |
125 | etree_type *exp; | |
126 | { | |
127 | base = exp; | |
128 | } | |
129 | ||
130 | static int done_tree = 0; | |
131 | ||
132 | void | |
133 | mri_draw_tree () | |
134 | { | |
891fa266 NC |
135 | if (done_tree) |
136 | return; | |
137 | ||
138 | #if 0 /* We don't bother with memory regions. */ | |
139 | /* Create the regions. */ | |
140 | { | |
141 | lang_memory_region_type *r; | |
5cc18311 | 142 | |
891fa266 NC |
143 | r = lang_memory_region_lookup("long"); |
144 | r->current = r->origin = exp_get_vma (base, (bfd_vma)0, "origin", | |
145 | lang_first_phase_enum); | |
146 | r->length = (bfd_size_type) exp_get_vma (0, (bfd_vma) ~((bfd_size_type)0), | |
147 | "length", lang_first_phase_enum); | |
148 | } | |
252b5132 | 149 | #endif |
5cc18311 | 150 | |
891fa266 | 151 | /* Now build the statements for the ldlang machine. */ |
252b5132 | 152 | |
891fa266 NC |
153 | /* Attatch the addresses of any which have addresses, |
154 | and add the ones not mentioned. */ | |
155 | if (address != (struct section_name_struct *)NULL) | |
252b5132 | 156 | { |
891fa266 NC |
157 | struct section_name_struct *alist; |
158 | struct section_name_struct *olist; | |
5cc18311 | 159 | |
891fa266 NC |
160 | if (order == (struct section_name_struct *)NULL) |
161 | order = address; | |
162 | ||
163 | for (alist = address; | |
164 | alist != (struct section_name_struct*)NULL; | |
5cc18311 | 165 | alist = alist->next) |
252b5132 | 166 | { |
891fa266 | 167 | int done = 0; |
5cc18311 | 168 | |
891fa266 NC |
169 | for (olist = order; |
170 | done == 0 && | |
171 | olist != (struct section_name_struct *)NULL; | |
5cc18311 | 172 | olist = olist->next) |
891fa266 | 173 | { |
5cc18311 | 174 | if (strcmp (alist->name, olist->name) == 0) |
891fa266 NC |
175 | { |
176 | olist->vma = alist->vma; | |
177 | done = 1; | |
178 | } | |
179 | } | |
5cc18311 | 180 | |
891fa266 NC |
181 | if (!done) |
182 | { | |
183 | /* Add this onto end of order list. */ | |
184 | mri_add_to_list (& order, alist->name, alist->vma, 0,0,0); | |
185 | } | |
252b5132 | 186 | } |
252b5132 RH |
187 | } |
188 | ||
252b5132 RH |
189 | /* If we're only supposed to load a subset of them in, then prune |
190 | the list. */ | |
5cc18311 | 191 | if (only_load != (struct section_name_struct *)NULL) |
252b5132 | 192 | { |
891fa266 NC |
193 | struct section_name_struct *ptr1; |
194 | struct section_name_struct *ptr2; | |
5cc18311 | 195 | |
891fa266 NC |
196 | if (order == (struct section_name_struct*)NULL) |
197 | order = only_load; | |
5cc18311 | 198 | |
891fa266 | 199 | /* See if this name is in the list, if it is then we can load it. */ |
5cc18311 KH |
200 | for (ptr1 = only_load; ptr1; ptr1 = ptr1->next) |
201 | for (ptr2 = order; ptr2; ptr2 = ptr2->next) | |
891fa266 NC |
202 | if (strcmp (ptr2->name, ptr1->name) == 0) |
203 | ptr2->ok_to_load = 1; | |
252b5132 | 204 | } |
5cc18311 | 205 | else |
891fa266 NC |
206 | { |
207 | /* No only load list, so everything is ok to load. */ | |
208 | struct section_name_struct *ptr; | |
5cc18311 | 209 | |
891fa266 NC |
210 | for (ptr = order; ptr; ptr=ptr->next) |
211 | ptr->ok_to_load = 1; | |
252b5132 RH |
212 | } |
213 | ||
891fa266 | 214 | /* Create the order of sections to load. */ |
5cc18311 | 215 | if (order != (struct section_name_struct *)NULL) |
252b5132 | 216 | { |
891fa266 NC |
217 | /* Been told to output the sections in a certain order. */ |
218 | struct section_name_struct *p = order; | |
5cc18311 KH |
219 | |
220 | while (p) | |
891fa266 NC |
221 | { |
222 | struct section_name_struct *aptr; | |
223 | etree_type *align = 0; | |
224 | etree_type *subalign = 0; | |
5cc18311 | 225 | |
891fa266 NC |
226 | /* See if an alignment has been specified. */ |
227 | for (aptr = alignment; aptr; aptr= aptr->next) | |
228 | if (strcmp (aptr->name, p->name) == 0) | |
229 | align = aptr->align; | |
230 | ||
231 | for (aptr = subalignment; aptr; aptr= aptr->next) | |
232 | if (strcmp (aptr->name, p->name) == 0) | |
233 | subalign = aptr->subalign; | |
234 | ||
235 | if (base == 0) | |
236 | base = p->vma ? p->vma :exp_nameop (NAME, "."); | |
237 | ||
238 | lang_enter_output_section_statement (p->name, base, | |
239 | p->ok_to_load ? 0 : noload_section, | |
240 | 1, align, subalign, | |
241 | (etree_type *) NULL); | |
242 | base = 0; | |
243 | lang_add_wild (p->name, false, (char *)NULL, false, false, NULL); | |
5cc18311 | 244 | |
891fa266 NC |
245 | /* If there is an alias for this section, add it too. */ |
246 | for (aptr = alias; aptr; aptr = aptr->next) | |
247 | if (strcmp (aptr->alias, p->name) == 0) | |
248 | lang_add_wild (aptr->name, false, (char *)NULL, false, false, NULL); | |
249 | ||
250 | lang_leave_output_section_statement | |
5cc18311 | 251 | (0, "*default*", (struct lang_output_section_phdr_list *) NULL, |
891fa266 NC |
252 | "*default*"); |
253 | ||
254 | p = p->next; | |
252b5132 | 255 | } |
252b5132 | 256 | } |
252b5132 RH |
257 | |
258 | done_tree = 1; | |
252b5132 | 259 | } |
891fa266 | 260 | |
252b5132 RH |
261 | void |
262 | mri_load (name) | |
263 | CONST char *name; | |
264 | { | |
265 | base = 0; | |
891fa266 NC |
266 | lang_add_input_file (name, |
267 | lang_input_file_is_file_enum, (char *)NULL); | |
5cc18311 | 268 | #if 0 |
891fa266 NC |
269 | lang_leave_output_section_statement (0,"*default*"); |
270 | #endif | |
252b5132 RH |
271 | } |
272 | ||
252b5132 RH |
273 | void |
274 | mri_order (name) | |
275 | CONST char *name; | |
276 | { | |
891fa266 | 277 | mri_add_to_list (& order, name, 0, 0,0,0); |
252b5132 RH |
278 | } |
279 | ||
5cc18311 | 280 | void |
252b5132 RH |
281 | mri_alias (want, is, isn) |
282 | CONST char *want; | |
283 | CONST char *is; | |
284 | int isn; | |
285 | { | |
891fa266 NC |
286 | if (!is) |
287 | { | |
288 | char buf[20]; | |
5cc18311 | 289 | |
891fa266 NC |
290 | /* Some sections are digits. */ |
291 | sprintf (buf, "%d", isn); | |
5cc18311 | 292 | |
891fa266 | 293 | is = xstrdup (buf); |
5cc18311 | 294 | |
891fa266 NC |
295 | if (is == NULL) |
296 | abort (); | |
297 | } | |
5cc18311 | 298 | |
891fa266 | 299 | mri_add_to_list (& alias, is, 0, want,0,0); |
252b5132 RH |
300 | } |
301 | ||
5cc18311 | 302 | void |
252b5132 RH |
303 | mri_name (name) |
304 | CONST char *name; | |
305 | { | |
891fa266 | 306 | lang_add_output (name, 1); |
252b5132 RH |
307 | } |
308 | ||
252b5132 RH |
309 | void |
310 | mri_format (name) | |
311 | CONST char *name; | |
312 | { | |
891fa266 NC |
313 | if (strcmp (name, "S") == 0) |
314 | lang_add_output_format ("srec", (char *) NULL, (char *) NULL, 1); | |
5cc18311 | 315 | |
891fa266 NC |
316 | else if (strcmp (name, "IEEE") == 0) |
317 | lang_add_output_format ("ieee", (char *) NULL, (char *) NULL, 1); | |
5cc18311 | 318 | |
891fa266 NC |
319 | else if (strcmp (name, "COFF") == 0) |
320 | lang_add_output_format ("coff-m68k", (char *) NULL, (char *) NULL, 1); | |
5cc18311 | 321 | |
891fa266 NC |
322 | else |
323 | einfo (_("%P%F: unknown format type %s\n"), name); | |
252b5132 RH |
324 | } |
325 | ||
252b5132 RH |
326 | void |
327 | mri_public (name, exp) | |
328 | CONST char *name; | |
329 | etree_type *exp; | |
330 | { | |
891fa266 | 331 | lang_add_assignment (exp_assop ('=', name, exp)); |
252b5132 RH |
332 | } |
333 | ||
5cc18311 | 334 | void |
252b5132 RH |
335 | mri_align (name, exp) |
336 | CONST char *name; | |
337 | etree_type *exp; | |
338 | { | |
891fa266 | 339 | mri_add_to_list (& alignment, name, 0, 0, exp, 0); |
252b5132 RH |
340 | } |
341 | ||
5cc18311 | 342 | void |
252b5132 RH |
343 | mri_alignmod (name, exp) |
344 | CONST char *name; | |
345 | etree_type *exp; | |
346 | { | |
891fa266 | 347 | mri_add_to_list (& subalignment, name, 0, 0, 0, exp); |
252b5132 RH |
348 | } |
349 | ||
5cc18311 | 350 | void |
252b5132 RH |
351 | mri_truncate (exp) |
352 | unsigned int exp; | |
353 | { | |
354 | symbol_truncate = exp; | |
355 | } |