Commit | Line | Data |
---|---|---|
2fa0b342 DHW |
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 | /* $Id$ | |
20 | * | |
21 | * $Log$ | |
22 | * Revision 1.1 1991/03/21 21:28:45 gumby | |
23 | * Initial revision | |
24 | * | |
25 | * Revision 1.3 1991/03/16 22:19:21 rich | |
26 | * pop | |
27 | * | |
28 | * Revision 1.2 1991/03/15 18:52:42 rich | |
29 | * pop | |
30 | * | |
31 | * Revision 1.1 1991/03/13 00:48:23 chrisb | |
32 | * Initial revision | |
33 | * | |
34 | * Revision 1.8 1991/03/10 09:31:28 rich | |
35 | * Modified Files: | |
36 | * Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c | |
37 | * ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h | |
38 | * ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c | |
39 | * ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c | |
40 | * ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h | |
41 | * | |
42 | * As of this round of changes, ld now builds on all hosts of (Intel960) | |
43 | * interest and copy passes my copy test on big endian hosts again. | |
44 | * | |
45 | * Revision 1.7 1991/03/09 03:31:03 sac | |
46 | * After a fatal info message, the output file is deleted. | |
47 | * | |
48 | * Revision 1.6 1991/03/09 03:25:06 sac | |
49 | * Added support for LONG, SHORT and BYTE keywords in scripts | |
50 | * | |
51 | * Revision 1.5 1991/03/06 21:59:31 sac | |
52 | * Completed G++ support | |
53 | * | |
54 | * Revision 1.4 1991/03/06 02:26:02 sac | |
55 | * Added support for constructor sections. | |
56 | * Remove parsing ambiguity. | |
57 | * Lint | |
58 | * | |
59 | * Revision 1.3 1991/02/22 17:15:01 sac | |
60 | * Added RCS keywords and copyrights | |
61 | * | |
62 | */ | |
63 | ||
64 | ||
65 | ||
66 | #include "sysdep.h" | |
67 | #include "bfd.h" | |
68 | ||
69 | #include "ld.h" | |
70 | #include "ldmain.h" | |
71 | #include "ldsym.h" | |
72 | #include "ldgram.tab.h" | |
73 | #include "ldmisc.h" | |
74 | #include "ldlang.h" | |
75 | #include "ldexp.h" | |
76 | #include "ld-emul.h" | |
77 | #include "ldlex.h" | |
78 | ||
79 | /* EXPORTS */ | |
80 | ||
81 | ||
82 | ||
83 | extern unsigned int undefined_global_sym_count; | |
84 | ||
85 | static char *startup_file; | |
86 | static lang_input_statement_type *first_file; | |
87 | lang_statement_list_type statement_list; | |
88 | lang_statement_list_type *stat_ptr = &statement_list; | |
89 | lang_statement_list_type lang_output_section_statement; | |
90 | lang_statement_list_type input_file_chain; | |
91 | lang_statement_list_type file_chain; | |
92 | extern char *current_file; | |
93 | static boolean placed_commons = false; | |
94 | ||
95 | boolean lang_float_flag; | |
96 | ||
97 | static lang_output_section_statement_type *default_common_section; | |
98 | ||
99 | ||
100 | /* FORWARDS */ | |
101 | PROTO(static void, print_statements,(void)); | |
102 | PROTO(static void, print_statement,(lang_statement_union_type *, | |
103 | lang_output_section_statement_type *)); | |
104 | ||
105 | ||
106 | ||
107 | /* EXPORTS */ | |
108 | boolean lang_has_input_file = false; | |
109 | ||
110 | ||
111 | extern bfd *output_bfd; | |
112 | size_t largest_section; | |
113 | ||
114 | ||
115 | extern enum bfd_architecture ldfile_output_architecture; | |
116 | extern unsigned long ldfile_output_machine; | |
117 | extern char *ldfile_output_machine_name; | |
118 | ||
119 | ||
120 | extern ldsym_type *symbol_head; | |
121 | ||
122 | bfd_vma print_dot; | |
123 | unsigned int commons_pending; | |
124 | ||
125 | ||
126 | ||
127 | ||
128 | extern args_type command_line; | |
129 | extern ld_config_type config; | |
130 | ||
131 | char *entry_symbol; | |
132 | ||
133 | ||
134 | ||
135 | lang_output_section_statement_type *create_object_symbols; | |
136 | ||
137 | extern boolean had_script; | |
138 | static boolean map_option_f; | |
139 | ||
140 | ||
141 | boolean had_output_filename = false; | |
142 | extern boolean write_map; | |
143 | ||
144 | ||
145 | ||
146 | ||
147 | ||
148 | ||
149 | size_t longest_section_name = 8; | |
150 | ||
151 | ||
152 | lang_input_statement_type *script_file; | |
153 | ||
154 | section_userdata_type common_section_userdata; | |
155 | asection common_section; | |
156 | ||
157 | #ifdef __STDC__ | |
158 | #define cat(a,b) a##b | |
159 | #else | |
160 | #define cat(a,b) a/**/b | |
161 | #endif | |
162 | ||
163 | #define new_stat(x,y) (cat(x,_type)*) new_statement(cat(x,_enum), sizeof(cat(x,_type)),y) | |
164 | ||
165 | #define outside_section_address(q) ( (q)->output_offset + (q)->output_section->vma) | |
166 | ||
167 | #define outside_symbol_address(q) ((q)->value + outside_section_address(q->section)) | |
168 | ||
169 | boolean option_longmap = false; | |
170 | ||
171 | static void lang_list_init(list) | |
172 | lang_statement_list_type *list; | |
173 | { | |
174 | list->head = (lang_statement_union_type *)NULL; | |
175 | list->tail = &list->head; | |
176 | } | |
177 | ||
178 | static void | |
179 | print_section(name) | |
180 | char *name; | |
181 | { | |
182 | printf("%*s", -longest_section_name, name); | |
183 | } | |
184 | static void | |
185 | print_space() | |
186 | { | |
187 | printf(" "); | |
188 | } | |
189 | static void | |
190 | print_nl() | |
191 | { | |
192 | printf("\n"); | |
193 | } | |
194 | static void | |
195 | print_address(value) | |
196 | bfd_vma value; | |
197 | { | |
198 | printf("%8lx", value); | |
199 | } | |
200 | static void | |
201 | print_size(value) | |
202 | size_t value; | |
203 | { | |
204 | printf("%5x", (unsigned)value); | |
205 | } | |
206 | static void | |
207 | print_alignment(value) | |
208 | unsigned int value; | |
209 | { | |
210 | printf("2**%2u",value); | |
211 | } | |
212 | static void | |
213 | print_fill(value) | |
214 | fill_type value; | |
215 | { | |
216 | printf("%04x",(unsigned)value); | |
217 | } | |
218 | ||
219 | ||
220 | static | |
221 | lang_statement_union_type *new_statement(type, size, list) | |
222 | enum statement_enum type; | |
223 | size_t size; | |
224 | lang_statement_list_type *list; | |
225 | { | |
226 | lang_statement_union_type *new = (lang_statement_union_type *) | |
227 | ldmalloc(size); | |
228 | new->header.type = type; | |
229 | new->header.next = (lang_statement_union_type *)NULL; | |
230 | lang_statement_append(list, new, &new->header.next); | |
231 | return new; | |
232 | } | |
233 | ||
234 | static lang_input_statement_type * | |
235 | new_afile(name, file_type, target) | |
236 | char *name; | |
237 | lang_input_file_enum_type file_type; | |
238 | char *target; | |
239 | { | |
240 | lang_input_statement_type *p = new_stat(lang_input_statement, | |
241 | stat_ptr); | |
242 | lang_has_input_file = true; | |
243 | p->target = target; | |
244 | switch (file_type) { | |
245 | case lang_input_file_is_symbols_only_enum: | |
246 | p->filename = name; | |
247 | p->is_archive =false; | |
248 | p->real = true; | |
249 | p->local_sym_name= name; | |
250 | p->just_syms_flag = true; | |
251 | p->search_dirs_flag = false; | |
252 | break; | |
253 | case lang_input_file_is_fake_enum: | |
254 | p->filename = name; | |
255 | p->is_archive =false; | |
256 | p->real = false; | |
257 | p->local_sym_name= name; | |
258 | p->just_syms_flag = false; | |
259 | p->search_dirs_flag =false; | |
260 | ||
261 | break; | |
262 | case lang_input_file_is_l_enum: | |
263 | p->is_archive = true; | |
264 | p->filename = name; | |
265 | p->real = true; | |
266 | p->local_sym_name = concat("-l",name,""); | |
267 | p->just_syms_flag = false; | |
268 | p->search_dirs_flag = true; | |
269 | break; | |
270 | ||
271 | case lang_input_file_is_search_file_enum: | |
272 | case lang_input_file_is_marker_enum: | |
273 | p->filename = name; | |
274 | p->is_archive =false; | |
275 | p->real = true; | |
276 | p->local_sym_name= name; | |
277 | p->just_syms_flag = false; | |
278 | p->search_dirs_flag =true; | |
279 | break; | |
280 | ||
281 | ||
282 | ||
283 | case lang_input_file_is_file_enum: | |
284 | p->filename = name; | |
285 | p->is_archive =false; | |
286 | p->real = true; | |
287 | p->local_sym_name= name; | |
288 | p->just_syms_flag = false; | |
289 | p->search_dirs_flag =false; | |
290 | break; | |
291 | ||
292 | ||
293 | default: | |
294 | FAIL(); | |
295 | } | |
296 | p->asymbols = (asymbol **)NULL; | |
297 | p->superfile = (lang_input_statement_type *)NULL; | |
298 | ||
299 | p->next_real_file = (lang_statement_union_type*)NULL; | |
300 | p->next = (lang_statement_union_type*)NULL; | |
301 | p->symbol_count = 0; | |
302 | p->common_output_section = (asection *)NULL; | |
303 | ||
304 | lang_statement_append(&input_file_chain, | |
305 | (lang_statement_union_type *)p, | |
306 | &p->next_real_file); | |
307 | return p; | |
308 | } | |
309 | ||
310 | lang_input_statement_type * | |
311 | lang_add_input_file(name, | |
312 | file_type, | |
313 | target) | |
314 | char *name; | |
315 | lang_input_file_enum_type file_type; | |
316 | char *target; | |
317 | { | |
318 | /* Look it up or build a new one */ | |
319 | ||
320 | lang_input_statement_type *p; | |
321 | ||
322 | for (p = (lang_input_statement_type *)input_file_chain.head; | |
323 | p != (lang_input_statement_type *)NULL; | |
324 | p = (lang_input_statement_type *)(p->next_real_file)) | |
325 | { | |
326 | /* Sometimes we have incomplete entries in here */ | |
327 | if (p->filename != (char *)NULL) { | |
328 | if(strcmp(name,p->filename) == 0) return p; | |
329 | } | |
330 | } | |
331 | ||
332 | return new_afile(name, file_type, target); | |
333 | } | |
334 | ||
335 | ||
336 | ||
337 | void | |
338 | lang_init() | |
339 | { | |
340 | ||
341 | stat_ptr= &statement_list; | |
342 | lang_list_init(stat_ptr); | |
343 | ||
344 | lang_list_init(&input_file_chain); | |
345 | lang_list_init(&lang_output_section_statement); | |
346 | lang_list_init(&file_chain); | |
347 | first_file = lang_add_input_file((char *)NULL, | |
348 | lang_input_file_is_marker_enum, | |
349 | (char *)NULL); | |
350 | ||
351 | } | |
352 | ||
353 | static void | |
354 | lang_init2() | |
355 | { | |
356 | script_file = lang_add_input_file("script file", | |
357 | lang_input_file_is_fake_enum, | |
358 | (char *)NULL); | |
359 | script_file->the_bfd = bfd_create("script file", output_bfd); | |
360 | script_file->symbol_count = 0; | |
361 | ||
362 | common_section.userdata = &common_section_userdata; | |
363 | ||
364 | } | |
365 | ||
366 | ||
367 | ||
368 | /* this function mainains a dictionary of regions. If the *default* | |
369 | region is asked for then a pointer to the first region is | |
370 | returned. If there is no first pointer then one is created | |
371 | */ | |
372 | ||
373 | static lang_memory_region_type *lang_memory_region_list; | |
374 | static lang_memory_region_type **lang_memory_region_list_tail = &lang_memory_region_list; | |
375 | ||
376 | lang_memory_region_type * | |
377 | lang_memory_region_lookup(name) | |
378 | char *name; | |
379 | { | |
380 | ||
381 | lang_memory_region_type *p = lang_memory_region_list; | |
382 | for (p = lang_memory_region_list; | |
383 | p != ( lang_memory_region_type *)NULL; | |
384 | p = p->next) { | |
385 | if (strcmp(p->name, name) == 0) { | |
386 | return p; | |
387 | } | |
388 | } | |
389 | if (strcmp(name,"*default*")==0) { | |
390 | /* This is the default region, dig out first one on the list */ | |
391 | if (lang_memory_region_list != (lang_memory_region_type*)NULL){ | |
392 | return lang_memory_region_list; | |
393 | } | |
394 | } | |
395 | { | |
396 | lang_memory_region_type *new = | |
397 | (lang_memory_region_type *)ldmalloc(sizeof(lang_memory_region_type)); | |
398 | new->name = name; | |
399 | new->next = (lang_memory_region_type *)NULL; | |
400 | ||
401 | *lang_memory_region_list_tail = new; | |
402 | lang_memory_region_list_tail = &new->next; | |
403 | new->origin = 0; | |
404 | new->length = ~0; | |
405 | new->current = 0; | |
406 | return new; | |
407 | } | |
408 | } | |
409 | ||
410 | ||
411 | ||
412 | lang_output_section_statement_type * | |
413 | lang_output_section_find(name) | |
414 | char *name; | |
415 | { | |
416 | lang_statement_union_type *u; | |
417 | lang_output_section_statement_type *lookup; | |
418 | ||
419 | for (u = lang_output_section_statement.head; | |
420 | u != (lang_statement_union_type *)NULL; | |
421 | u = lookup->next) | |
422 | { | |
423 | lookup = &u->output_section_statement; | |
424 | if (strcmp(name, lookup->name)==0) { | |
425 | return lookup; | |
426 | } | |
427 | } | |
428 | return (lang_output_section_statement_type *)NULL; | |
429 | } | |
430 | ||
431 | lang_output_section_statement_type * | |
432 | lang_output_section_statement_lookup(name) | |
433 | char *name; | |
434 | ||
435 | { | |
436 | lang_output_section_statement_type *lookup; | |
437 | lookup =lang_output_section_find(name); | |
438 | if (lookup == (lang_output_section_statement_type *)NULL) { | |
439 | ||
440 | lookup =(lang_output_section_statement_type *) | |
441 | new_stat(lang_output_section_statement, stat_ptr); | |
442 | lookup->region = (lang_memory_region_type *)NULL; | |
443 | lookup->fill = 0; | |
444 | lookup->block_value = 1; | |
445 | lookup->name = name; | |
446 | ||
447 | lookup->next = (lang_statement_union_type*)NULL; | |
448 | lookup->bfd_section = (asection *)NULL; | |
449 | lookup->processed = false; | |
450 | lookup->addr_tree = (etree_type *)NULL; | |
451 | lang_list_init(&lookup->children); | |
452 | ||
453 | lang_statement_append(&lang_output_section_statement, | |
454 | (lang_statement_union_type *)lookup, | |
455 | &lookup->next); | |
456 | } | |
457 | return lookup; | |
458 | } | |
459 | ||
460 | ||
461 | ||
462 | ||
463 | ||
464 | static void | |
465 | print_flags(outfile, ignore_flags) | |
466 | FILE *outfile; | |
467 | lang_section_flags_type *ignore_flags; | |
468 | { | |
469 | fprintf(outfile,"("); | |
470 | #if 0 | |
471 | if (flags->flag_read) fprintf(outfile,"R"); | |
472 | if (flags->flag_write) fprintf(outfile,"W"); | |
473 | if (flags->flag_executable) fprintf(outfile,"X"); | |
474 | if (flags->flag_loadable) fprintf(outfile,"L"); | |
475 | #endif | |
476 | fprintf(outfile,")"); | |
477 | } | |
478 | ||
479 | void | |
480 | lang_map(outfile) | |
481 | FILE *outfile; | |
482 | { | |
483 | lang_memory_region_type *m; | |
484 | fprintf(outfile,"**MEMORY CONFIGURATION**\n\n"); | |
485 | ||
486 | fprintf(outfile,"name\t\torigin\t\tlength\t\tattributes\n"); | |
487 | for (m = lang_memory_region_list; | |
488 | m != (lang_memory_region_type *)NULL; | |
489 | m = m->next) | |
490 | { | |
491 | fprintf(outfile,"%-16s", m->name); | |
492 | ||
493 | fprintf(outfile,"%08lx\t%08lx\t", m->origin, m->length); | |
494 | print_flags(outfile, &m->flags); | |
495 | fprintf(outfile,"\n"); | |
496 | } | |
497 | fprintf(outfile,"\n\n**LINK EDITOR MEMORY MAP**\n\n"); | |
498 | fprintf(outfile,"output\t\tinput\t\tvirtual\n"); | |
499 | fprintf(outfile,"section\t\tsection\t\taddress\tsize\n\n"); | |
500 | ||
501 | print_statements(); | |
502 | ||
503 | } | |
504 | ||
505 | /* | |
506 | * | |
507 | */ | |
508 | static void init_os(s) | |
509 | lang_output_section_statement_type *s; | |
510 | { | |
511 | section_userdata_type *new = | |
512 | (section_userdata_type *) | |
513 | ldmalloc(sizeof(section_userdata_type)); | |
514 | ||
515 | s->bfd_section = bfd_make_section(output_bfd, s->name); | |
516 | s->bfd_section->output_section = s->bfd_section; | |
517 | s->bfd_section->flags = SEC_NO_FLAGS; | |
518 | /* We initialize an output sections output offset to minus its own */ | |
519 | /* vma to allow us to output a section through itself */ | |
520 | s->bfd_section->output_offset = 0; | |
521 | get_userdata( s->bfd_section) = new; | |
522 | } | |
523 | ||
524 | static void | |
525 | wild_doit(ptr, section,output, file) | |
526 | lang_statement_list_type *ptr; | |
527 | asection *section; | |
528 | lang_output_section_statement_type *output; | |
529 | lang_input_statement_type *file; | |
530 | { | |
531 | if(output->bfd_section == (asection *)NULL) | |
532 | { | |
533 | init_os(output); | |
534 | } | |
535 | ||
536 | if (section != (asection *)NULL | |
537 | && section->output_section == (asection *)NULL) { | |
538 | /* Add a section reference to the list */ | |
539 | lang_input_section_type *new = new_stat(lang_input_section, ptr); | |
540 | ||
541 | new->section = section; | |
542 | new->ifile = file; | |
543 | section->output_section = output->bfd_section; | |
544 | section->output_section->flags |= section->flags; | |
545 | if (section->alignment_power > output->bfd_section->alignment_power) { | |
546 | output->bfd_section->alignment_power = section->alignment_power; | |
547 | } | |
548 | ||
549 | } | |
550 | } | |
551 | ||
552 | static asection * | |
553 | our_bfd_get_section_by_name(abfd, section) | |
554 | bfd *abfd; | |
555 | char *section; | |
556 | { | |
557 | return bfd_get_section_by_name(abfd, section); | |
558 | ||
559 | } | |
560 | static void | |
561 | wild_section(ptr, section, file , output) | |
562 | lang_wild_statement_type *ptr; | |
563 | char *section; | |
564 | lang_input_statement_type *file; | |
565 | lang_output_section_statement_type *output; | |
566 | { | |
567 | asection *s; | |
568 | if (section == (char *)NULL) { | |
569 | /* Do the creation to all sections in the file */ | |
570 | for (s = file->the_bfd->sections; s != (asection *)NULL; s=s->next) { | |
571 | wild_doit(&ptr->children, s, output, file); | |
572 | } | |
573 | } | |
574 | else { | |
575 | /* Do the creation to the named section only */ | |
576 | wild_doit(&ptr->children, | |
577 | our_bfd_get_section_by_name(file->the_bfd, section), | |
578 | output, file); | |
579 | } | |
580 | ||
581 | ||
582 | ||
583 | } | |
584 | ||
585 | ||
586 | ||
587 | static | |
588 | lang_input_statement_type *lookup_name(name, target) | |
589 | char *name; | |
590 | char *target; | |
591 | { | |
592 | lang_input_statement_type *search; | |
593 | for(search = (lang_input_statement_type *)input_file_chain.head; | |
594 | search != (lang_input_statement_type *)NULL; | |
595 | search = (lang_input_statement_type *)search->next_real_file) | |
596 | { | |
597 | if (search->filename == (char *)NULL && name == (char *)NULL) { | |
598 | return search; | |
599 | } | |
600 | if (search->filename != (char *)NULL && name != (char *)NULL) { | |
601 | if (strcmp(search->filename, name) == 0) { | |
602 | Q_read_file_symbols(search); | |
603 | return search; | |
604 | } | |
605 | } | |
606 | } | |
607 | ||
608 | /* There isn't an afile entry for this file yet, this must be */ | |
609 | /* because the name has only appeared inside a load script and not */ | |
610 | /* on the command line */ | |
611 | search = new_afile(name, lang_input_file_is_file_enum, target); | |
612 | Q_read_file_symbols(search); | |
613 | return search; | |
614 | } | |
615 | ||
616 | static void | |
617 | ||
618 | wild(s, section, file, target, output) | |
619 | lang_wild_statement_type *s; | |
620 | char *section; | |
621 | char *file; | |
622 | char *target; | |
623 | lang_output_section_statement_type *output; | |
624 | { | |
625 | lang_input_statement_type *f; | |
626 | if (file == (char *)NULL) { | |
627 | /* Perform the iteration over all files in the list */ | |
628 | for (f = (lang_input_statement_type *)file_chain.head; | |
629 | f != (lang_input_statement_type *)NULL; | |
630 | f = (lang_input_statement_type *)f->next) { | |
631 | wild_section(s, section, f, output); | |
632 | } | |
633 | } | |
634 | else { | |
635 | /* Perform the iteration over a single file */ | |
636 | wild_section( s, section, lookup_name(file, target), output); | |
637 | } | |
638 | } | |
639 | ||
640 | /* | |
641 | read in all the files | |
642 | */ | |
643 | static bfd * | |
644 | open_output(name, target) | |
645 | char *name; | |
646 | char *target; | |
647 | { | |
648 | extern char *output_filename; | |
649 | bfd * output = bfd_openw(name, target); | |
650 | output_filename = name; | |
651 | if (output == (bfd *)NULL) | |
652 | { | |
653 | if (bfd_error == invalid_target) { | |
654 | info("%P%F target %s not found\n", target); | |
655 | } | |
656 | info("%P%F problem opening output file %s, %E", name); | |
657 | } | |
658 | ||
659 | output->flags |= D_PAGED; | |
660 | bfd_set_format(output, bfd_object); | |
661 | return output; | |
662 | } | |
663 | extern char *default_target; | |
664 | static void | |
665 | lang_phase_0(sh,target) | |
666 | lang_statement_union_type *sh; | |
667 | char *target; | |
668 | { | |
669 | lang_statement_union_type *s = (lang_statement_union_type *)sh; | |
670 | for (; s != (lang_statement_union_type *)NULL ; s = s->next) | |
671 | { | |
672 | switch (s->header.type) { | |
673 | case lang_output_section_statement_enum: | |
674 | lang_phase_0(s->output_section_statement.children.head, | |
675 | target); | |
676 | break; | |
677 | case lang_output_statement_enum: | |
678 | #if 1 | |
679 | output_bfd = open_output(s->output_statement.name, | |
680 | target == (char *)NULL ? | |
681 | default_target : target); | |
682 | ldemul_set_output_arch(); | |
683 | #endif | |
684 | break; | |
685 | case lang_target_statement_enum: | |
686 | target = s->target_statement.target; | |
687 | break; | |
688 | case lang_wild_statement_enum: | |
689 | /* Maybe we should load the file's symbols */ | |
690 | if (s->wild_statement.filename) { | |
691 | (void) lookup_name(s->wild_statement.filename, target); | |
692 | } | |
693 | break; | |
694 | /* Attatch this to the current output section */ | |
695 | case lang_common_statement_enum: | |
696 | case lang_fill_statement_enum: | |
697 | case lang_input_section_enum: | |
698 | case lang_object_symbols_statement_enum: | |
699 | case lang_address_statement_enum: | |
700 | case lang_data_statement_enum: | |
701 | break; | |
702 | case lang_afile_asection_pair_statement_enum: | |
703 | ||
704 | FAIL(); | |
705 | break; | |
706 | ||
707 | case lang_input_statement_enum: | |
708 | if (s->input_statement.real == true) { | |
709 | s->input_statement.target = target; | |
710 | lookup_name(s->input_statement.filename, target); | |
711 | } | |
712 | break; | |
713 | case lang_assignment_statement_enum: | |
714 | #if 0 | |
715 | (void) exp_fold_tree(s->assignment_statement.exp, | |
716 | output_section, | |
717 | false); | |
718 | #endif | |
719 | break; | |
720 | ||
721 | case lang_padding_statement_enum: | |
722 | ||
723 | break; | |
724 | } | |
725 | } | |
726 | ||
727 | } | |
728 | ||
729 | /* If there are [COMMONS] statements, put a wild one into the bss section */ | |
730 | ||
731 | static void | |
732 | lang_reasonable_defaults() | |
733 | { | |
734 | default_common_section = | |
735 | lang_output_section_statement_lookup(".bss"); | |
736 | if (placed_commons == false) { | |
737 | lang_wild_statement_type *new = | |
738 | new_stat(lang_wild_statement, | |
739 | &default_common_section->children); | |
740 | new->section_name = "COMMON"; | |
741 | new->filename = (char *)NULL; | |
742 | lang_list_init(&new->children); | |
743 | } | |
744 | } | |
745 | ||
746 | static void lang() | |
747 | { | |
748 | if (had_script == false) { | |
749 | parse_line(ldemul_get_script()); | |
750 | } | |
751 | ||
752 | lang_reasonable_defaults(); | |
753 | lang_phase_0(statement_list.head,default_target); | |
754 | } | |
755 | ||
756 | ||
757 | /* Open input files and attatch to output sections */ | |
758 | static void | |
759 | lang_open_input(s, target, output_section_statement) | |
760 | lang_statement_union_type *s; | |
761 | char *target; | |
762 | lang_output_section_statement_type *output_section_statement; | |
763 | { | |
764 | for (; s != (lang_statement_union_type *)NULL ; s = s->next) | |
765 | { | |
766 | switch (s->header.type) { | |
767 | case lang_wild_statement_enum: | |
768 | wild(&s->wild_statement, s->wild_statement.section_name, | |
769 | s->wild_statement.filename, target, | |
770 | output_section_statement); | |
771 | ||
772 | break; | |
773 | ||
774 | case lang_output_section_statement_enum: | |
775 | lang_open_input(s->output_section_statement.children.head, | |
776 | target, | |
777 | &s->output_section_statement); | |
778 | break; | |
779 | case lang_output_statement_enum: | |
780 | break; | |
781 | case lang_target_statement_enum: | |
782 | target = s->target_statement.target; | |
783 | break; | |
784 | case lang_common_statement_enum: | |
785 | case lang_fill_statement_enum: | |
786 | case lang_input_section_enum: | |
787 | case lang_object_symbols_statement_enum: | |
788 | case lang_data_statement_enum: | |
789 | break; | |
790 | case lang_afile_asection_pair_statement_enum: | |
791 | FAIL(); | |
792 | break; | |
793 | ||
794 | case lang_assignment_statement_enum: | |
795 | case lang_padding_statement_enum: | |
796 | ||
797 | break; | |
798 | case lang_address_statement_enum: | |
799 | /* Mark the specified section with the supplied address */ | |
800 | { | |
801 | lang_output_section_statement_type *os = | |
802 | lang_output_section_statement_lookup | |
803 | (s->address_statement.section_name); | |
804 | os->addr_tree = s->address_statement.address; | |
805 | } | |
806 | break; | |
807 | case lang_input_statement_enum: | |
808 | /* A standard input statement, has no wildcards */ | |
809 | /* Q_read_file_symbols(&s->input_statement);*/ | |
810 | break; | |
811 | } | |
812 | } | |
813 | } | |
814 | ||
815 | ||
816 | ||
817 | ||
818 | ||
819 | static void | |
820 | print_output_section_statement(output_section_statement) | |
821 | lang_output_section_statement_type *output_section_statement; | |
822 | { | |
823 | asection *section = output_section_statement->bfd_section; | |
824 | print_nl(); | |
825 | print_section(output_section_statement->name); | |
826 | ||
827 | if (section) { | |
828 | print_dot = section->vma; | |
829 | print_space(); | |
830 | print_section(""); | |
831 | print_space(); | |
832 | print_address(section->vma); | |
833 | print_space(); | |
834 | print_size(section->size); | |
835 | print_space(); | |
836 | print_alignment(section->alignment_power); | |
837 | print_space(); | |
838 | #if 0 | |
839 | printf("%s flags", output_section_statement->region->name); | |
840 | print_flags(stdout, &output_section_statement->flags); | |
841 | #endif | |
842 | ||
843 | } | |
844 | else { | |
845 | printf("No attached output section"); | |
846 | } | |
847 | print_nl(); | |
848 | print_statement(output_section_statement->children.head, | |
849 | output_section_statement); | |
850 | ||
851 | } | |
852 | ||
853 | static void | |
854 | print_assignment(assignment, output_section) | |
855 | lang_assignment_statement_type *assignment; | |
856 | lang_output_section_statement_type *output_section; | |
857 | { | |
858 | etree_value_type result; | |
859 | print_section(""); | |
860 | print_space(); | |
861 | print_section(""); | |
862 | print_space(); | |
863 | print_address(print_dot); | |
864 | print_space(); | |
865 | result = exp_fold_tree(assignment->exp->assign.src, | |
866 | output_section, | |
867 | lang_final_phase_enum, | |
868 | print_dot, | |
869 | &print_dot); | |
870 | ||
871 | if (result.valid) { | |
872 | print_address(result.value); | |
873 | } | |
874 | else | |
875 | { | |
876 | printf("*undefined*"); | |
877 | } | |
878 | print_space(); | |
879 | exp_print_tree(stdout, assignment->exp); | |
880 | printf("\n"); | |
881 | } | |
882 | ||
883 | static void | |
884 | print_input_statement(statm) | |
885 | lang_input_statement_type *statm; | |
886 | { | |
887 | printf("LOAD %s\n",statm->filename); | |
888 | } | |
889 | ||
890 | static void print_symbol(q) | |
891 | asymbol *q; | |
892 | { | |
893 | print_section(""); | |
894 | printf(" "); | |
895 | print_section(""); | |
896 | printf(" "); | |
897 | print_address(outside_symbol_address(q)); | |
898 | printf(" %s", q->name ? q->name : " "); | |
899 | print_nl(); | |
900 | } | |
901 | static void | |
902 | print_input_section(in) | |
903 | lang_input_section_type *in; | |
904 | { | |
905 | asection *i = in->section; | |
906 | ||
907 | if(i->size != 0) { | |
908 | print_section(""); | |
909 | printf(" "); | |
910 | print_section(i->name); | |
911 | printf(" "); | |
912 | if (i->output_section) { | |
913 | print_address(i->output_section->vma + i->output_offset); | |
914 | printf(" "); | |
915 | print_size(i->size); | |
916 | printf(" "); | |
917 | print_alignment(i->alignment_power); | |
918 | printf(" "); | |
919 | if (in->ifile) { | |
920 | bfd *abfd = in->ifile->the_bfd; | |
921 | printf(" %s ",abfd->xvec->name); | |
922 | if(abfd->my_archive != (bfd *)NULL) { | |
923 | printf("[%s]%s", abfd->my_archive->filename, | |
924 | abfd->filename); | |
925 | } | |
926 | else { | |
927 | printf("%s", abfd->filename); | |
928 | } | |
929 | print_nl(); | |
930 | ||
931 | /* Find all the symbols in this file defined in this section */ | |
932 | { | |
933 | asymbol **p; | |
934 | for (p = in->ifile->asymbols; *p; p++) { | |
935 | asymbol *q = *p; | |
936 | ||
937 | if (bfd_get_section(q) == i && q->flags & BSF_GLOBAL) { | |
938 | print_symbol(q); | |
939 | } | |
940 | } | |
941 | } | |
942 | } | |
943 | else { | |
944 | print_nl(); | |
945 | } | |
946 | ||
947 | ||
948 | print_dot = outside_section_address(i) + i->size; | |
949 | } | |
950 | else { | |
951 | printf("No output section allocated\n"); | |
952 | } | |
953 | } | |
954 | } | |
955 | static void | |
956 | print_common_statement() | |
957 | { | |
958 | ldsym_type *lgs; | |
959 | print_section(""); | |
960 | print_space(); | |
961 | print_section(common_section.output_section->name); | |
962 | print_space(); | |
963 | print_address(common_section.output_offset + | |
964 | common_section.output_section->vma); | |
965 | print_space(); | |
966 | print_size(common_section.size); | |
967 | print_space(); | |
968 | printf("(common)"); | |
969 | print_nl(); | |
970 | /* Print out all the global symbols */ | |
971 | ||
972 | ||
973 | for (lgs = symbol_head; lgs != (ldsym_type *)NULL; lgs = | |
974 | lgs->next) { | |
975 | if (lgs->sdefs_chain) { | |
976 | asymbol *def = *(lgs->sdefs_chain); | |
977 | if (def->section == &common_section) { | |
978 | print_symbol(def); | |
979 | } | |
980 | } | |
981 | ||
982 | } | |
983 | print_dot = common_section.output_offset + | |
984 | common_section.output_section->vma + common_section.size; | |
985 | ||
986 | ||
987 | } | |
988 | static void | |
989 | print_fill_statement(fill) | |
990 | lang_fill_statement_type *fill; | |
991 | { | |
992 | printf("FILL mask "); | |
993 | print_fill( fill->fill); | |
994 | } | |
995 | ||
996 | static void | |
997 | print_data_statement(data) | |
998 | lang_data_statement_type *data; | |
999 | { | |
1000 | /* bfd_vma value; */ | |
1001 | print_section(""); | |
1002 | print_space(); | |
1003 | print_section(""); | |
1004 | print_space(); | |
1005 | ASSERT(print_dot == data->output_vma); | |
1006 | ||
1007 | print_address(data->output_vma); | |
1008 | print_space(); | |
1009 | print_address(data->value); | |
1010 | print_space(); | |
1011 | switch (data->type) { | |
1012 | case BYTE : | |
1013 | printf("BYTE "); | |
1014 | print_dot += BYTE_SIZE; | |
1015 | break; | |
1016 | case SHORT: | |
1017 | printf("SHORT "); | |
1018 | print_dot += SHORT_SIZE; | |
1019 | break; | |
1020 | case LONG: | |
1021 | printf("LONG "); | |
1022 | print_dot += LONG_SIZE; | |
1023 | break; | |
1024 | } | |
1025 | ||
1026 | exp_print_tree(stdout, data->exp); | |
1027 | ||
1028 | printf("\n"); | |
1029 | } | |
1030 | ||
1031 | ||
1032 | static void | |
1033 | print_padding_statement(s) | |
1034 | lang_padding_statement_type *s; | |
1035 | { | |
1036 | print_section(""); | |
1037 | print_space(); | |
1038 | print_section("*fill*"); | |
1039 | print_space(); | |
1040 | print_address(s->output_offset + s->output_section->vma); | |
1041 | print_space(); | |
1042 | print_size(s->size); | |
1043 | print_space(); | |
1044 | print_fill(s->fill); | |
1045 | print_nl(); | |
1046 | } | |
1047 | ||
1048 | static void print_wild_statement(w,os) | |
1049 | lang_wild_statement_type *w; | |
1050 | lang_output_section_statement_type *os; | |
1051 | { | |
1052 | if (w->filename != (char *)NULL) { | |
1053 | printf("%s",w->filename); | |
1054 | } | |
1055 | else { | |
1056 | printf("*"); | |
1057 | } | |
1058 | if (w->section_name != (char *)NULL) { | |
1059 | printf("(%s)",w->section_name); | |
1060 | } | |
1061 | else { | |
1062 | printf("(*)"); | |
1063 | } | |
1064 | print_nl(); | |
1065 | print_statement(w->children.head, os); | |
1066 | ||
1067 | } | |
1068 | static void | |
1069 | print_statement(s, os) | |
1070 | lang_statement_union_type *s; | |
1071 | lang_output_section_statement_type *os; | |
1072 | { | |
1073 | while (s) { | |
1074 | switch (s->header.type) { | |
1075 | case lang_wild_statement_enum: | |
1076 | print_wild_statement(&s->wild_statement, os); | |
1077 | break; | |
1078 | default: | |
1079 | printf("Fail with %d\n",s->header.type); | |
1080 | FAIL(); | |
1081 | break; | |
1082 | case lang_address_statement_enum: | |
1083 | printf("address\n"); | |
1084 | break; | |
1085 | case lang_common_statement_enum: | |
1086 | print_common_statement(); | |
1087 | break; | |
1088 | case lang_object_symbols_statement_enum: | |
1089 | printf("object symbols\n"); | |
1090 | break; | |
1091 | case lang_fill_statement_enum: | |
1092 | print_fill_statement(&s->fill_statement); | |
1093 | break; | |
1094 | case lang_data_statement_enum: | |
1095 | print_data_statement(&s->data_statement); | |
1096 | break; | |
1097 | ||
1098 | ||
1099 | case lang_input_section_enum: | |
1100 | print_input_section(&s->input_section); | |
1101 | break; | |
1102 | case lang_padding_statement_enum: | |
1103 | print_padding_statement(&s->padding_statement); | |
1104 | break; | |
1105 | case lang_output_section_statement_enum: | |
1106 | print_output_section_statement(&s->output_section_statement); | |
1107 | break; | |
1108 | case lang_assignment_statement_enum: | |
1109 | print_assignment(&s->assignment_statement, | |
1110 | os); | |
1111 | break; | |
1112 | ||
1113 | ||
1114 | case lang_target_statement_enum: | |
1115 | printf("TARGET(%s)\n", s->target_statement.target); | |
1116 | break; | |
1117 | case lang_output_statement_enum: | |
1118 | printf("OUTPUT(%s)\n", s->output_statement.name); | |
1119 | break; | |
1120 | case lang_input_statement_enum: | |
1121 | print_input_statement(&s->input_statement); | |
1122 | break; | |
1123 | case lang_afile_asection_pair_statement_enum: | |
1124 | FAIL(); | |
1125 | break; | |
1126 | } | |
1127 | s = s->next; | |
1128 | } | |
1129 | } | |
1130 | ||
1131 | ||
1132 | static void | |
1133 | print_statements() | |
1134 | { | |
1135 | print_statement(statement_list.head, | |
1136 | (lang_output_section_statement_type *)NULL); | |
1137 | } | |
1138 | ||
1139 | static bfd_vma | |
1140 | insert_pad(this_ptr, fill, power, output_section_statement, dot) | |
1141 | lang_statement_union_type **this_ptr; | |
1142 | fill_type fill; | |
1143 | unsigned int power; | |
1144 | asection * output_section_statement; | |
1145 | bfd_vma dot; | |
1146 | { | |
1147 | /* Align this section first to the | |
1148 | input sections requirement, then | |
1149 | to the output section's requirement. | |
1150 | If this alignment is > than any seen before, | |
1151 | then record it too. Perform the alignment by | |
1152 | inserting a magic 'padding' statement. | |
1153 | */ | |
1154 | ||
1155 | unsigned int alignment_needed = align_power(dot, power) - dot; | |
1156 | ||
1157 | if (alignment_needed != 0) | |
1158 | { | |
1159 | lang_statement_union_type *new = | |
1160 | (lang_statement_union_type *) | |
1161 | ldmalloc(sizeof(lang_padding_statement_type)); | |
1162 | /* Link into existing chain */ | |
1163 | new->header.next = *this_ptr; | |
1164 | *this_ptr = new; | |
1165 | new->header.type = lang_padding_statement_enum; | |
1166 | new->padding_statement.output_section = output_section_statement; | |
1167 | new->padding_statement.output_offset = | |
1168 | dot - output_section_statement->vma; | |
1169 | new->padding_statement.fill = fill; | |
1170 | new->padding_statement.size = alignment_needed; | |
1171 | } | |
1172 | ||
1173 | ||
1174 | /* Remember the most restrictive alignment */ | |
1175 | if (power > output_section_statement->alignment_power) { | |
1176 | output_section_statement->alignment_power = power; | |
1177 | } | |
1178 | output_section_statement->size += alignment_needed; | |
1179 | return alignment_needed + dot; | |
1180 | ||
1181 | } | |
1182 | ||
1183 | /* | |
1184 | size_common runs run though each global symboxl, and works | |
1185 | out how big the common section will be. | |
1186 | */ | |
1187 | ||
1188 | static bfd_vma | |
1189 | size_common(output_section_statement, this_ptr, dot) | |
1190 | lang_output_section_statement_type *output_section_statement; | |
1191 | lang_statement_union_type **this_ptr; | |
1192 | bfd_vma dot; | |
1193 | { | |
1194 | extern ldsym_type *symbol_head; | |
1195 | ldsym_type *sp; | |
1196 | /* Make sure that each symbol is only defined once. | |
1197 | Allocate common symbols | |
1198 | Make the ref chain point to the defining asymbol. | |
1199 | */ | |
1200 | /* Now, for each symbol, verify that it is defined globally at most once. | |
1201 | Put the global value into the symbol entry. | |
1202 | Common symbols are allocated here, in the BSS section. | |
1203 | Each defined symbol is given a '->defined' field | |
1204 | which is the correct N_ code for its definition, | |
1205 | except in the case of common symbols with -r. | |
1206 | Then make all the references point at the symbol entry | |
1207 | instead of being chained together. */ | |
1208 | ||
1209 | ||
1210 | common_section.name = output_section_statement->bfd_section->name; | |
1211 | common_section.output_section = output_section_statement->bfd_section; | |
1212 | common_section.output_offset = | |
1213 | dot - output_section_statement->bfd_section->vma; | |
1214 | if (config.relocateable_output == false || | |
1215 | command_line.force_common_definition== true) { | |
1216 | dot = insert_pad(this_ptr, | |
1217 | 0x0, 4, output_section_statement->bfd_section, dot); | |
1218 | ||
1219 | for (sp = symbol_head; sp != (ldsym_type *)NULL; sp = sp->next) | |
1220 | { | |
1221 | /* Attatch this symbol to the correct output section*/ | |
1222 | ||
1223 | /* Allocate as common if wanted */ | |
1224 | ||
1225 | if (sp->scoms_chain ) | |
1226 | ||
1227 | { | |
1228 | unsigned long com = (*(sp->scoms_chain))->value; | |
1229 | /* Work out what alignment this common item s | |
1230 | hould be put on. Anything < int is int aligned, | |
1231 | anything bigger is self aligned, | |
1232 | up to the restriction of the machine */ | |
1233 | ||
1234 | unsigned int align = sizeof(int); | |
1235 | ||
1236 | /* Round up size of object to nearest int */ | |
1237 | com = ALIGN(com, sizeof(int)); | |
1238 | /* See what alignment is necessary -*/ | |
1239 | if (com) { | |
1240 | while ((com & align)==0) align <<=1; | |
1241 | /* FIXME */ | |
1242 | if (align > 8) { | |
1243 | align = 8; | |
1244 | } | |
1245 | } | |
1246 | dot = ALIGN(dot, align); | |
1247 | ||
1248 | ||
1249 | /* Transmogrify this from a common symbol | |
1250 | into a definition of a symbol in common | |
1251 | */ | |
1252 | sp->sdefs_chain = sp->scoms_chain; | |
1253 | ||
1254 | { | |
1255 | asymbol *com_ptr = *(sp->sdefs_chain); | |
1256 | ||
1257 | sp->scoms_chain = (asymbol **)NULL; | |
1258 | commons_pending--; | |
1259 | /* Assign address, but keep section relative */ | |
1260 | ||
1261 | /* Force the symbol to belong in the bss section */ | |
1262 | com_ptr->flags = BSF_EXPORT | BSF_GLOBAL ; | |
1263 | com_ptr->section = &common_section; | |
1264 | common_section.size += com; | |
1265 | if (write_map) | |
1266 | { | |
1267 | printf ("Allocating common %s: %lx at %lx\n", | |
1268 | sp->name, | |
1269 | com, | |
1270 | com_ptr->value); | |
1271 | } | |
1272 | com_ptr->value = common_section.size; | |
1273 | } | |
1274 | } | |
1275 | } | |
1276 | } | |
1277 | if (dot > | |
1278 | (common_section.output_section->vma + | |
1279 | common_section.output_section->size)) { | |
1280 | common_section.output_section->size = | |
1281 | dot - common_section.output_section->vma; | |
1282 | } | |
1283 | return dot + common_section.size; | |
1284 | } | |
1285 | ||
1286 | static bfd_vma | |
1287 | size_input_section( this_ptr, output_section_statement, fill, dot) | |
1288 | lang_statement_union_type **this_ptr; | |
1289 | lang_output_section_statement_type*output_section_statement; | |
1290 | unsigned short fill; | |
1291 | bfd_vma dot; | |
1292 | { | |
1293 | lang_input_section_type *is = &((*this_ptr)->input_section); | |
1294 | asection *i = is->section; | |
1295 | ||
1296 | dot = insert_pad(this_ptr, fill, i->alignment_power, | |
1297 | output_section_statement->bfd_section, dot); | |
1298 | ||
1299 | /* remember the largest size so we can malloc the largest area */ | |
1300 | /* needed for the output stage */ | |
1301 | if (i->size > largest_section) { | |
1302 | largest_section = i->size; | |
1303 | } | |
1304 | ||
1305 | /* Remember where in the output section this input section goes */ | |
1306 | i->output_offset = dot - output_section_statement->bfd_section->vma; | |
1307 | ||
1308 | /* Mark how big the output section must be to contain this now */ | |
1309 | dot += i->size; | |
1310 | output_section_statement->bfd_section->size = | |
1311 | dot - output_section_statement->bfd_section->vma; | |
1312 | ||
1313 | ||
1314 | return dot ; | |
1315 | } | |
1316 | ||
1317 | ||
1318 | /* Work out the size of the output sections | |
1319 | from the sizes of the input sections */ | |
1320 | static bfd_vma | |
1321 | lang_size_sections(s, output_section_statement, prev, fill, dot) | |
1322 | lang_statement_union_type *s; | |
1323 | lang_output_section_statement_type * output_section_statement; | |
1324 | lang_statement_union_type **prev; | |
1325 | unsigned short fill; | |
1326 | bfd_vma dot; | |
1327 | { | |
1328 | /* Size up the sections from their constituent parts */ | |
1329 | for (; s != (lang_statement_union_type *)NULL ; s = s->next) | |
1330 | { | |
1331 | switch (s->header.type) { | |
1332 | case lang_output_section_statement_enum: | |
1333 | { | |
1334 | bfd_vma after; | |
1335 | lang_output_section_statement_type *os = | |
1336 | &(s->output_section_statement); | |
1337 | /* The start of a section */ | |
1338 | ||
1339 | if (os->addr_tree == (etree_type *)NULL) { | |
1340 | /* No address specified for this section, get one | |
1341 | from the region specification | |
1342 | */ | |
1343 | if (os->region == (lang_memory_region_type *)NULL) { | |
1344 | os->region = lang_memory_region_lookup("*default*"); | |
1345 | } | |
1346 | dot = os->region->current; | |
1347 | } | |
1348 | else { | |
1349 | etree_value_type r ; | |
1350 | r = exp_fold_tree(os->addr_tree, | |
1351 | (lang_output_section_statement_type *)NULL, | |
1352 | lang_allocating_phase_enum, | |
1353 | dot, &dot); | |
1354 | if (r.valid == false) { | |
1355 | info("%F%S: non constant address expression for section %s\n", | |
1356 | os->name); | |
1357 | } | |
1358 | dot = r.value; | |
1359 | } | |
1360 | /* The section starts here */ | |
1361 | /* First, align to what the section needs */ | |
1362 | ||
1363 | dot = align_power(dot, os->bfd_section->alignment_power); | |
1364 | os->bfd_section->vma = dot; | |
1365 | os->bfd_section->output_offset = 0; | |
1366 | ||
1367 | (void) lang_size_sections(os->children.head, os, &os->children.head, | |
1368 | os->fill, dot); | |
1369 | /* Ignore the size of the input sections, use the vma and size to */ | |
1370 | /* align against */ | |
1371 | ||
1372 | ||
1373 | after = ALIGN(os->bfd_section->vma + | |
1374 | os->bfd_section->size, | |
1375 | os->block_value) ; | |
1376 | ||
1377 | ||
1378 | os->bfd_section->size = after - os->bfd_section->vma; | |
1379 | dot = os->bfd_section->vma + os->bfd_section->size; | |
1380 | os->processed = true; | |
1381 | ||
1382 | /* Replace into region ? */ | |
1383 | if (os->addr_tree == (etree_type *)NULL | |
1384 | && os->region !=(lang_memory_region_type*)NULL ) { | |
1385 | os->region->current = dot; | |
1386 | } | |
1387 | } | |
1388 | ||
1389 | break; | |
1390 | ||
1391 | case lang_data_statement_enum: | |
1392 | { | |
1393 | unsigned int size; | |
1394 | s->data_statement.output_vma = dot; | |
1395 | s->data_statement.output_section = | |
1396 | output_section_statement->bfd_section; | |
1397 | ||
1398 | switch (s->data_statement.type) { | |
1399 | case LONG: | |
1400 | size = LONG_SIZE; | |
1401 | break; | |
1402 | case SHORT: | |
1403 | size = SHORT_SIZE; | |
1404 | break; | |
1405 | case BYTE: | |
1406 | size = BYTE_SIZE; | |
1407 | break; | |
1408 | ||
1409 | } | |
1410 | dot += size; | |
1411 | output_section_statement->bfd_section->size += size; | |
1412 | } | |
1413 | break; | |
1414 | ||
1415 | case lang_wild_statement_enum: | |
1416 | ||
1417 | dot = lang_size_sections(s->wild_statement.children.head, | |
1418 | output_section_statement, | |
1419 | &s->wild_statement.children.head, | |
1420 | ||
1421 | fill, dot); | |
1422 | ||
1423 | break; | |
1424 | ||
1425 | case lang_object_symbols_statement_enum: | |
1426 | create_object_symbols = output_section_statement; | |
1427 | break; | |
1428 | case lang_output_statement_enum: | |
1429 | ||
1430 | case lang_target_statement_enum: | |
1431 | break; | |
1432 | case lang_common_statement_enum: | |
1433 | dot = size_common(output_section_statement, prev, dot); | |
1434 | ||
1435 | break; | |
1436 | ||
1437 | case lang_input_section_enum: | |
1438 | dot = size_input_section(prev, | |
1439 | output_section_statement, | |
1440 | output_section_statement->fill, dot); | |
1441 | break; | |
1442 | case lang_input_statement_enum: | |
1443 | break; | |
1444 | case lang_fill_statement_enum: | |
1445 | fill = s->fill_statement.fill; | |
1446 | break; | |
1447 | case lang_assignment_statement_enum: | |
1448 | { | |
1449 | bfd_vma newdot = dot; | |
1450 | exp_fold_tree(s->assignment_statement.exp, | |
1451 | output_section_statement, | |
1452 | lang_allocating_phase_enum, | |
1453 | dot, | |
1454 | &newdot); | |
1455 | ||
1456 | if (newdot != dot) | |
1457 | /* We've been moved ! so insert a pad */ | |
1458 | { | |
1459 | lang_statement_union_type *new = | |
1460 | (lang_statement_union_type *) | |
1461 | ldmalloc(sizeof(lang_padding_statement_type)); | |
1462 | /* Link into existing chain */ | |
1463 | new->header.next = *prev; | |
1464 | *prev = new; | |
1465 | new->header.type = lang_padding_statement_enum; | |
1466 | new->padding_statement.output_section = | |
1467 | output_section_statement->bfd_section; | |
1468 | new->padding_statement.output_offset = | |
1469 | dot - output_section_statement->bfd_section->vma; | |
1470 | new->padding_statement.fill = fill; | |
1471 | new->padding_statement.size = newdot - dot; | |
1472 | output_section_statement->bfd_section->size += | |
1473 | new->padding_statement.size; | |
1474 | dot = newdot; | |
1475 | } | |
1476 | } | |
1477 | ||
1478 | break; | |
1479 | case lang_padding_statement_enum: | |
1480 | FAIL(); | |
1481 | break; | |
1482 | default: | |
1483 | FAIL(); | |
1484 | break; | |
1485 | case lang_address_statement_enum: | |
1486 | break; | |
1487 | } | |
1488 | prev = &s->header.next; | |
1489 | } | |
1490 | return dot; | |
1491 | } | |
1492 | ||
1493 | ||
1494 | static bfd_vma | |
1495 | lang_do_assignments(s, output_section_statement, fill, dot) | |
1496 | lang_statement_union_type *s; | |
1497 | lang_output_section_statement_type * output_section_statement; | |
1498 | unsigned short fill; | |
1499 | bfd_vma dot; | |
1500 | { | |
1501 | ||
1502 | for (; s != (lang_statement_union_type *)NULL ; s = s->next) | |
1503 | { | |
1504 | switch (s->header.type) { | |
1505 | case lang_output_section_statement_enum: | |
1506 | { | |
1507 | lang_output_section_statement_type *os = | |
1508 | &(s->output_section_statement); | |
1509 | dot = os->bfd_section->vma; | |
1510 | (void) lang_do_assignments(os->children.head, os, os->fill, dot); | |
1511 | dot = os->bfd_section->vma + os->bfd_section->size; | |
1512 | } | |
1513 | break; | |
1514 | case lang_wild_statement_enum: | |
1515 | ||
1516 | dot = lang_do_assignments(s->wild_statement.children.head, | |
1517 | output_section_statement, | |
1518 | fill, dot); | |
1519 | ||
1520 | break; | |
1521 | ||
1522 | case lang_object_symbols_statement_enum: | |
1523 | case lang_output_statement_enum: | |
1524 | case lang_target_statement_enum: | |
1525 | case lang_common_statement_enum: | |
1526 | break; | |
1527 | case lang_data_statement_enum: | |
1528 | { | |
1529 | etree_value_type value ; | |
1530 | value = exp_fold_tree(s->data_statement.exp, | |
1531 | 0, lang_final_phase_enum, dot, &dot); | |
1532 | s->data_statement.value = value.value; | |
1533 | if (value.valid == false) info("%F%P: Invalid data statement\n"); | |
1534 | } | |
1535 | switch (s->data_statement.type) { | |
1536 | case LONG: | |
1537 | dot += LONG_SIZE; | |
1538 | break; | |
1539 | case SHORT: | |
1540 | dot += SHORT_SIZE; | |
1541 | break; | |
1542 | case BYTE: | |
1543 | dot += BYTE_SIZE; | |
1544 | break; | |
1545 | } | |
1546 | break; | |
1547 | case lang_input_section_enum: | |
1548 | { | |
1549 | asection *in = s->input_section.section; | |
1550 | dot += in->size; | |
1551 | } | |
1552 | break; | |
1553 | ||
1554 | case lang_input_statement_enum: | |
1555 | break; | |
1556 | case lang_fill_statement_enum: | |
1557 | fill = s->fill_statement.fill; | |
1558 | break; | |
1559 | case lang_assignment_statement_enum: | |
1560 | { | |
1561 | exp_fold_tree(s->assignment_statement.exp, | |
1562 | output_section_statement, | |
1563 | lang_final_phase_enum, | |
1564 | dot, | |
1565 | &dot); | |
1566 | } | |
1567 | ||
1568 | break; | |
1569 | case lang_padding_statement_enum: | |
1570 | dot += s->padding_statement.size; | |
1571 | break; | |
1572 | default: | |
1573 | FAIL(); | |
1574 | break; | |
1575 | case lang_address_statement_enum: | |
1576 | break; | |
1577 | } | |
1578 | ||
1579 | } | |
1580 | return dot; | |
1581 | } | |
1582 | ||
1583 | ||
1584 | ||
1585 | static void lang_relocate_globals() | |
1586 | { | |
1587 | ||
1588 | /* | |
1589 | Each ldsym_type maintains a chain of pointers to asymbols which | |
1590 | references the definition. Replace each pointer to the referenence | |
1591 | with a pointer to only one place, preferably the definition. If | |
1592 | the defintion isn't available then the common symbol, and if | |
1593 | there isn't one of them then choose one reference. | |
1594 | */ | |
1595 | ||
1596 | FOR_EACH_LDSYM(lgs) { | |
1597 | asymbol *it; | |
1598 | if (lgs->sdefs_chain) { | |
1599 | it = *(lgs->sdefs_chain); | |
1600 | } | |
1601 | else if (lgs->scoms_chain != (asymbol **)NULL) { | |
1602 | it = *(lgs->scoms_chain); | |
1603 | } | |
1604 | else if (lgs->srefs_chain != (asymbol **)NULL) { | |
1605 | it = *(lgs->srefs_chain); | |
1606 | } | |
1607 | else { | |
1608 | FAIL(); | |
1609 | } | |
1610 | if (it != (asymbol *)NULL) | |
1611 | { | |
1612 | asymbol **ptr= lgs->srefs_chain; | |
1613 | ||
1614 | while (ptr != (asymbol **)NULL) { | |
1615 | asymbol *ref = *ptr; | |
1616 | *ptr = it; | |
1617 | ptr = (asymbol **)(ref->udata); | |
1618 | } | |
1619 | } | |
1620 | } | |
1621 | } | |
1622 | ||
1623 | ||
1624 | ||
1625 | /* now that all the jiggery pokery is finished, copy important data from | |
1626 | * out internal form to the bfd way. Also create a section | |
1627 | * for each dummy file | |
1628 | */ | |
1629 | ||
1630 | static void | |
1631 | lang_create_output_section_statements() | |
1632 | { | |
1633 | lang_statement_union_type*os; | |
1634 | for (os = lang_output_section_statement.head; | |
1635 | os != (lang_statement_union_type*)NULL; | |
1636 | os = os->output_section_statement.next) { | |
1637 | lang_output_section_statement_type *s = | |
1638 | &os->output_section_statement; | |
1639 | init_os(s); | |
1640 | } | |
1641 | script_file->the_bfd->sections = output_bfd->sections; | |
1642 | } | |
1643 | ||
1644 | static void | |
1645 | lang_finish() | |
1646 | { | |
1647 | ldsym_type *lgs; | |
1648 | ||
1649 | if (entry_symbol == (char *)NULL) { | |
1650 | /* No entry has been specified, look for start */ | |
1651 | entry_symbol = "start"; | |
1652 | } | |
1653 | lgs = ldsym_get_soft(entry_symbol); | |
1654 | if (lgs && lgs->sdefs_chain) { | |
1655 | asymbol *sy = *(lgs->sdefs_chain); | |
1656 | /* We can set the entry address*/ | |
1657 | bfd_set_start_address(output_bfd, | |
1658 | outside_symbol_address(sy)); | |
1659 | ||
1660 | } | |
1661 | else { | |
1662 | /* Can't find anything reasonable, | |
1663 | use the first address in the text section | |
1664 | */ | |
1665 | asection *ts = bfd_get_section_by_name(output_bfd, ".text"); | |
1666 | if (ts) { | |
1667 | bfd_set_start_address(output_bfd, ts->vma); | |
1668 | } | |
1669 | } | |
1670 | } | |
1671 | ||
1672 | /* By now we know the target architecture, and we may have an */ | |
1673 | /* ldfile_output_machine_name */ | |
1674 | static void | |
1675 | lang_check() | |
1676 | { | |
1677 | lang_statement_union_type *file; | |
1678 | ||
1679 | ||
1680 | for (file = file_chain.head; | |
1681 | file != (lang_statement_union_type *)NULL; | |
1682 | file=file->input_statement.next) | |
1683 | { | |
1684 | /* Inspect the architecture and ensure we're linking like | |
1685 | with like | |
1686 | */ | |
1687 | ||
1688 | if (bfd_arch_compatible( file->input_statement.the_bfd, | |
1689 | output_bfd, | |
1690 | &ldfile_output_architecture, | |
1691 | &ldfile_output_machine)) { | |
1692 | bfd_set_arch_mach(output_bfd, | |
1693 | ldfile_output_architecture, ldfile_output_machine); | |
1694 | } | |
1695 | else { | |
1696 | enum bfd_architecture this_architecture = | |
1697 | bfd_get_architecture(file->input_statement.the_bfd); | |
1698 | unsigned long this_machine = | |
1699 | bfd_get_machine(file->input_statement.the_bfd); | |
1700 | ||
1701 | info("%I: architecture %s", | |
1702 | file, | |
1703 | bfd_printable_arch_mach(this_architecture, this_machine)); | |
1704 | info(" incompatible with output %s\n", | |
1705 | bfd_printable_arch_mach(ldfile_output_architecture, | |
1706 | ldfile_output_machine)); | |
1707 | ldfile_output_architecture = this_architecture; | |
1708 | ldfile_output_machine = this_machine; | |
1709 | bfd_set_arch_mach(output_bfd, | |
1710 | ldfile_output_architecture, | |
1711 | ldfile_output_machine); | |
1712 | ||
1713 | ||
1714 | } | |
1715 | } | |
1716 | } | |
1717 | ||
1718 | ||
1719 | /* | |
1720 | * run through all the global common symbols and tie them | |
1721 | * to the output section requested. | |
1722 | */ | |
1723 | ||
1724 | static void | |
1725 | lang_common() | |
1726 | { | |
1727 | ldsym_type *lgs; | |
1728 | if (config.relocateable_output == false || | |
1729 | command_line.force_common_definition== true) { | |
1730 | for (lgs = symbol_head; | |
1731 | lgs != (ldsym_type *)NULL; | |
1732 | lgs=lgs->next) | |
1733 | { | |
1734 | asymbol *com ; | |
1735 | size_t size; | |
1736 | size_t align; | |
1737 | if (lgs->scoms_chain != (asymbol **)NULL) { | |
1738 | ||
1739 | com = *(lgs->scoms_chain); | |
1740 | size = com->value; | |
1741 | align = sizeof(int); | |
1742 | /* Round up size of object to nearest int */ | |
1743 | size = ALIGN(size, sizeof(int)); | |
1744 | /* Force alignment */ | |
1745 | if (size) { | |
1746 | while ((size & align)==0) align<<=1; | |
1747 | if (align > 8) { | |
1748 | align = 8; | |
1749 | } | |
1750 | } | |
1751 | /* Change from a common symbol into a definition of | |
1752 | a symbol */ | |
1753 | lgs->sdefs_chain = lgs->scoms_chain; | |
1754 | lgs->scoms_chain = (asymbol **)NULL; | |
1755 | commons_pending--; | |
1756 | /* Point to the correct common section */ | |
1757 | com->section = | |
1758 | ((lang_input_statement_type *) | |
1759 | (com->the_bfd->usrdata))->common_section; | |
1760 | /* Fix the size of the common section */ | |
1761 | ||
1762 | ||
1763 | com->flags = BSF_EXPORT | BSF_GLOBAL; | |
1764 | ||
1765 | if (write_map) | |
1766 | { | |
1767 | printf ("Allocating common %s: %x at %x\n", | |
1768 | lgs->name, | |
1769 | (unsigned) size, | |
1770 | (unsigned) com->section->size); | |
1771 | } | |
1772 | com->value = com->section->size; | |
1773 | com->section->size += size; | |
1774 | } | |
1775 | } | |
1776 | } | |
1777 | } | |
1778 | ||
1779 | /* | |
1780 | run through the input files and ensure that every input | |
1781 | section has somewhere to go. If one is found without | |
1782 | a destination then create an input request and place it | |
1783 | into the statement tree. | |
1784 | */ | |
1785 | ||
1786 | static void lang_place_orphans() | |
1787 | { | |
1788 | lang_input_statement_type *file; | |
1789 | for (file = (lang_input_statement_type*)file_chain.head; | |
1790 | file != (lang_input_statement_type*)NULL; | |
1791 | file = (lang_input_statement_type*)file->next) { | |
1792 | asection *s; | |
1793 | for (s = file->the_bfd->sections; | |
1794 | s != (asection *)NULL; | |
1795 | s = s->next) { | |
1796 | if ( s->output_section == (asection *)NULL) { | |
1797 | /* This section of the file is not attatched, root | |
1798 | around for a sensible place for it to go */ | |
1799 | ||
1800 | if (file->common_section == s) { | |
1801 | /* This is a lonely common section which must | |
1802 | have come from an archive. We attatch to the | |
1803 | section with the wildcard */ | |
1804 | wild_doit(&default_common_section->children, s, | |
1805 | default_common_section, file); | |
1806 | } | |
1807 | else { | |
1808 | lang_output_section_statement_type *os = | |
1809 | lang_output_section_statement_lookup(s->name); | |
1810 | ||
1811 | wild_doit(&os->children, s, os, file); | |
1812 | } | |
1813 | } | |
1814 | } | |
1815 | ||
1816 | } | |
1817 | } | |
1818 | ||
1819 | ||
1820 | /* | |
1821 | * phase_2 | |
1822 | * | |
1823 | * peformed after every file has been opened and symbols read | |
1824 | */ | |
1825 | static void | |
1826 | lang_phase_2() | |
1827 | { | |
1828 | lang_init2(); | |
1829 | ||
1830 | lang_create_output_section_statements(); | |
1831 | lang_open_input(statement_list.head, (char *)NULL, | |
1832 | ( lang_output_section_statement_type *)NULL); | |
1833 | lang_place_orphans(); | |
1834 | lang_common(); | |
1835 | ||
1836 | ldemul_before_allocation(); | |
1837 | ||
1838 | lang_size_sections(statement_list.head, | |
1839 | (lang_output_section_statement_type *)NULL, | |
1840 | &(statement_list.head), 0, (bfd_vma)0); | |
1841 | ldemul_after_allocation(); | |
1842 | /* Do it once again now that we know the sizes of everything */ | |
1843 | ||
1844 | lang_do_assignments(statement_list.head, | |
1845 | (lang_output_section_statement_type *)NULL, | |
1846 | 0, (bfd_vma)0); | |
1847 | ||
1848 | ||
1849 | ||
1850 | lang_check(); | |
1851 | ||
1852 | lang_relocate_globals(); | |
1853 | ||
1854 | ||
1855 | lang_finish(); | |
1856 | } | |
1857 | ||
1858 | ||
1859 | ||
1860 | ||
1861 | void | |
1862 | lang_set_flags(ptr, flags) | |
1863 | lang_section_flags_type *ptr; | |
1864 | char *flags; | |
1865 | { | |
1866 | boolean state = true; | |
1867 | ptr->flag_read = false; | |
1868 | ptr->flag_write = false; | |
1869 | ptr->flag_executable = false; | |
1870 | ptr->flag_loadable= false; | |
1871 | while (*flags) | |
1872 | { | |
1873 | if (*flags == '!') { | |
1874 | state = false; | |
1875 | flags++; | |
1876 | } | |
1877 | else state = true; | |
1878 | switch (*flags) { | |
1879 | case 'R': | |
1880 | ptr->flag_read = state; | |
1881 | break; | |
1882 | case 'W': | |
1883 | ptr->flag_write = state; | |
1884 | break; | |
1885 | case 'X': | |
1886 | ptr->flag_executable= state; | |
1887 | break; | |
1888 | case 'L': | |
1889 | ptr->flag_loadable= state; | |
1890 | break; | |
1891 | default: | |
1892 | info("%P%F illegal syntax in flags\n"); | |
1893 | break; | |
1894 | } | |
1895 | flags++; | |
1896 | } | |
1897 | } | |
1898 | ||
1899 | ||
1900 | ||
1901 | void | |
1902 | lang_for_each_file(func) | |
1903 | void (*func)(); | |
1904 | { | |
1905 | lang_input_statement_type *f; | |
1906 | for (f = (lang_input_statement_type *)file_chain.head; | |
1907 | f != (lang_input_statement_type *)NULL; | |
1908 | f = (lang_input_statement_type *)f->next) | |
1909 | { | |
1910 | func(f); | |
1911 | } | |
1912 | } | |
1913 | ||
1914 | ||
1915 | void | |
1916 | lang_for_each_input_section(func) | |
1917 | void (*func)(); | |
1918 | { | |
1919 | lang_input_statement_type *f; | |
1920 | for (f = (lang_input_statement_type *)file_chain.head; | |
1921 | f != (lang_input_statement_type *)NULL; | |
1922 | f = (lang_input_statement_type *)f->next) | |
1923 | { | |
1924 | asection *s; | |
1925 | for (s = f->the_bfd->sections; | |
1926 | s != (asection *)NULL; | |
1927 | s = s->next) { | |
1928 | func(f->the_bfd, s); | |
1929 | } | |
1930 | } | |
1931 | } | |
1932 | ||
1933 | ||
1934 | ||
1935 | void | |
1936 | ldlang_add_file(entry) | |
1937 | lang_input_statement_type *entry; | |
1938 | { | |
1939 | lang_has_input_file = true; | |
1940 | lang_statement_append(&file_chain, | |
1941 | (lang_statement_union_type *)entry, | |
1942 | &entry->next); | |
1943 | } | |
1944 | ||
1945 | ||
1946 | ||
1947 | void | |
1948 | lang_add_output(name) | |
1949 | char *name; | |
1950 | { | |
1951 | lang_output_statement_type *new = new_stat(lang_output_statement, | |
1952 | stat_ptr); | |
1953 | new->name = name; | |
1954 | had_output_filename = true; | |
1955 | } | |
1956 | ||
1957 | ||
1958 | static lang_output_section_statement_type *current_section; | |
1959 | ||
1960 | void | |
1961 | lang_enter_output_section_statement(output_section_statement_name, | |
1962 | address_exp, | |
1963 | block_value) | |
1964 | char *output_section_statement_name; | |
1965 | etree_type *address_exp; | |
1966 | bfd_vma block_value; | |
1967 | { | |
1968 | lang_output_section_statement_type *os; | |
1969 | current_section = | |
1970 | os = | |
1971 | lang_output_section_statement_lookup(output_section_statement_name); | |
1972 | ||
1973 | ||
1974 | /* Add this statement to tree */ | |
1975 | /* add_statement(lang_output_section_statement_enum, | |
1976 | output_section_statement);*/ | |
1977 | /* Make next things chain into subchain of this */ | |
1978 | ||
1979 | if (os->addr_tree == | |
1980 | (etree_type *)NULL) { | |
1981 | os->addr_tree = | |
1982 | address_exp; | |
1983 | } | |
1984 | os->block_value = block_value; | |
1985 | stat_ptr = & os->children; | |
1986 | ||
1987 | } | |
1988 | ||
1989 | ||
1990 | void | |
1991 | lang_final() | |
1992 | { | |
1993 | if (had_output_filename == false) { | |
1994 | lang_add_output("a.out"); | |
1995 | } | |
1996 | ||
1997 | ||
1998 | } | |
1999 | ||
2000 | ||
2001 | ||
2002 | ||
2003 | ||
2004 | asymbol *create_symbol(name, flags, section) | |
2005 | char *name; | |
2006 | flagword flags; | |
2007 | asection *section; | |
2008 | { | |
2009 | extern lang_input_statement_type *script_file; | |
2010 | asymbol **def_ptr = (asymbol **)ldmalloc(sizeof(asymbol **)); | |
2011 | /* Add this definition to script file */ | |
2012 | asymbol *def = (asymbol *)bfd_make_empty_symbol(script_file->the_bfd); | |
2013 | def->name = name; | |
2014 | def->udata = 0; | |
2015 | def->flags = flags; | |
2016 | def->section = section; | |
2017 | ||
2018 | *def_ptr = def; | |
2019 | Q_enter_global_ref(def_ptr); | |
2020 | return def; | |
2021 | } | |
2022 | ||
2023 | ||
2024 | void | |
2025 | lang_process() | |
2026 | { | |
2027 | lang(); | |
2028 | lang_phase_2(); | |
2029 | } | |
2030 | ||
2031 | ||
2032 | /* EXPORTED TO YACC */ | |
2033 | void | |
2034 | lang_section_start(name, address) | |
2035 | char *name; | |
2036 | etree_type *address; | |
2037 | { | |
2038 | lang_address_statement_type *ad =new_stat(lang_address_statement, stat_ptr); | |
2039 | ad->section_name = name; | |
2040 | ad->address = address; | |
2041 | } | |
2042 | void lang_add_entry(name) | |
2043 | char *name; | |
2044 | { | |
2045 | entry_symbol = name; | |
2046 | } | |
2047 | ||
2048 | void | |
2049 | lang_add_target(name) | |
2050 | char *name; | |
2051 | { | |
2052 | lang_target_statement_type *new = new_stat(lang_target_statement, | |
2053 | stat_ptr); | |
2054 | new->target = name; | |
2055 | ||
2056 | } | |
2057 | void | |
2058 | lang_add_wild(section_name, filename) | |
2059 | char *section_name; | |
2060 | char *filename; | |
2061 | { | |
2062 | lang_wild_statement_type *new = new_stat(lang_wild_statement, | |
2063 | stat_ptr); | |
2064 | ||
2065 | if (section_name != (char *)NULL && strcmp(section_name,"COMMON") == 0) | |
2066 | { | |
2067 | placed_commons = true; | |
2068 | } | |
2069 | new->section_name = section_name; | |
2070 | new->filename = filename; | |
2071 | lang_list_init(&new->children); | |
2072 | } | |
2073 | ||
2074 | void | |
2075 | lang_add_map(name) | |
2076 | char *name; | |
2077 | { | |
2078 | while (*name) { | |
2079 | switch (*name) { | |
2080 | case 'F': | |
2081 | map_option_f = true; | |
2082 | break; | |
2083 | } | |
2084 | name++; | |
2085 | } | |
2086 | } | |
2087 | ||
2088 | void lang_add_fill(exp) | |
2089 | int exp; | |
2090 | { | |
2091 | lang_fill_statement_type *new = new_stat(lang_fill_statement, | |
2092 | stat_ptr); | |
2093 | new->fill = exp; | |
2094 | } | |
2095 | ||
2096 | void lang_add_data(type, exp) | |
2097 | int type; | |
2098 | union etree_union *exp; | |
2099 | { | |
2100 | ||
2101 | lang_data_statement_type *new = new_stat(lang_data_statement, | |
2102 | stat_ptr); | |
2103 | new->exp = exp; | |
2104 | new->type = type; | |
2105 | ||
2106 | } | |
2107 | void | |
2108 | lang_add_assignment(exp) | |
2109 | etree_type *exp; | |
2110 | { | |
2111 | lang_assignment_statement_type *new = new_stat(lang_assignment_statement, | |
2112 | stat_ptr); | |
2113 | new->exp = exp; | |
2114 | } | |
2115 | ||
2116 | void | |
2117 | lang_add_attribute(attribute) | |
2118 | enum statement_enum attribute; | |
2119 | { | |
2120 | new_statement(attribute, sizeof(lang_statement_union_type),stat_ptr); | |
2121 | } | |
2122 | ||
2123 | ||
2124 | ||
2125 | void | |
2126 | lang_startup(name) | |
2127 | char *name; | |
2128 | { | |
2129 | if (startup_file != (char *)NULL) { | |
2130 | info("%P%FMultiple STARTUP files\n"); | |
2131 | } | |
2132 | first_file->filename = name; | |
2133 | first_file->local_sym_name = name; | |
2134 | ||
2135 | startup_file= name; | |
2136 | } | |
2137 | void | |
2138 | lang_float(maybe) | |
2139 | boolean maybe; | |
2140 | { | |
2141 | lang_float_flag = maybe; | |
2142 | } | |
2143 | ||
2144 | void | |
2145 | lang_leave_output_section_statement(fill, memspec) | |
2146 | bfd_vma fill; | |
2147 | char *memspec; | |
2148 | { | |
2149 | current_section->fill = fill; | |
2150 | current_section->region = lang_memory_region_lookup(memspec); | |
2151 | stat_ptr = &statement_list; | |
2152 | } | |
2153 | ||
2154 | void | |
2155 | lang_abs_symbol_at_end_of(section, name) | |
2156 | char *section; | |
2157 | char *name; | |
2158 | { | |
2159 | extern bfd *output_bfd; | |
2160 | extern asymbol *create_symbol(); | |
2161 | asection *s = bfd_get_section_by_name(output_bfd, section); | |
2162 | /* Add a symbol called _end */ | |
2163 | asymbol *def = create_symbol(name, | |
2164 | BSF_GLOBAL | BSF_EXPORT | | |
2165 | BSF_ABSOLUTE, | |
2166 | (asection *)NULL); | |
2167 | if (s != (asection *)NULL) { | |
2168 | def->value = s->vma + s->size; | |
2169 | } | |
2170 | else { | |
2171 | def->value = 0; | |
2172 | } | |
2173 | } | |
2174 | ||
2175 | void | |
2176 | lang_statement_append(list, element, field) | |
2177 | lang_statement_list_type *list; | |
2178 | lang_statement_union_type *element; | |
2179 | lang_statement_union_type **field; | |
2180 | { | |
2181 | *(list->tail) = element; | |
2182 | list->tail = field; | |
2183 | } | |
2184 | ||
2185 | ||
2186 | static void | |
2187 | lang_for_each_statement_worker(func, s) | |
2188 | void (*func)(); | |
2189 | lang_statement_union_type *s; | |
2190 | { | |
2191 | for (; s != (lang_statement_union_type *)NULL ; s = s->next) | |
2192 | { | |
2193 | func(s); | |
2194 | ||
2195 | switch (s->header.type) { | |
2196 | case lang_output_section_statement_enum: | |
2197 | lang_for_each_statement_worker | |
2198 | (func, | |
2199 | s->output_section_statement.children.head); | |
2200 | break; | |
2201 | case lang_wild_statement_enum: | |
2202 | lang_for_each_statement_worker | |
2203 | (func, | |
2204 | s->wild_statement.children.head); | |
2205 | break; | |
2206 | case lang_data_statement_enum: | |
2207 | case lang_object_symbols_statement_enum: | |
2208 | case lang_output_statement_enum: | |
2209 | case lang_target_statement_enum: | |
2210 | case lang_common_statement_enum: | |
2211 | case lang_input_section_enum: | |
2212 | case lang_input_statement_enum: | |
2213 | case lang_fill_statement_enum: | |
2214 | case lang_assignment_statement_enum: | |
2215 | case lang_padding_statement_enum: | |
2216 | case lang_address_statement_enum: | |
2217 | break; | |
2218 | default: | |
2219 | FAIL(); | |
2220 | break; | |
2221 | } | |
2222 | } | |
2223 | } | |
2224 | ||
2225 | void lang_for_each_statement(func) | |
2226 | void (*func)(); | |
2227 | { | |
2228 | lang_for_each_statement_worker(func, | |
2229 | statement_list.head); | |
2230 | ||
2231 | } |