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