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