Commit | Line | Data |
---|---|---|
252b5132 | 1 | /* obj-format for ieee-695 records. |
aef6203b | 2 | Copyright 1991, 1992, 1993, 1994, 1997, 2000, 2001, 2002, 2003, 2005 |
28e4f854 | 3 | Free Software Foundation, Inc. |
252b5132 RH |
4 | |
5 | This file is part of GAS, the GNU Assembler. | |
6 | ||
7 | GAS 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 | GAS 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 GAS; see the file COPYING. If not, write to the Free | |
4b4da160 NC |
19 | Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA |
20 | 02110-1301, USA. */ | |
252b5132 | 21 | |
28e4f854 | 22 | /* Created by Steve Chamberlain <steve@cygnus.com>. */ |
252b5132 | 23 | |
28e4f854 KH |
24 | /* This will hopefully become the port through which bfd and gas talk, |
25 | for the moment, only ieee is known to work well. */ | |
252b5132 RH |
26 | |
27 | #include "bfd.h" | |
28 | #include "as.h" | |
29 | #include "subsegs.h" | |
30 | #include "output-file.h" | |
31 | #include "frags.h" | |
32 | ||
33 | bfd *abfd; | |
34 | ||
28e4f854 KH |
35 | /* How many addresses does the .align take? */ |
36 | ||
252b5132 RH |
37 | static relax_addressT |
38 | relax_align (address, alignment) | |
28e4f854 KH |
39 | /* Address now. */ |
40 | register relax_addressT address; | |
41 | ||
42 | /* Alignment (binary). */ | |
43 | register long alignment; | |
252b5132 RH |
44 | { |
45 | relax_addressT mask; | |
46 | relax_addressT new_address; | |
47 | ||
48 | mask = ~((~0) << alignment); | |
49 | new_address = (address + mask) & (~mask); | |
50 | return (new_address - address); | |
28e4f854 KH |
51 | } |
52 | ||
53 | /* Calculate the size of the frag chain | |
54 | and create a bfd section to contain all of it. */ | |
252b5132 | 55 | |
252b5132 | 56 | static void |
1994a7c7 | 57 | size_section (abfd, idx) |
28e4f854 | 58 | bfd *abfd; |
1994a7c7 | 59 | unsigned int idx; |
252b5132 RH |
60 | { |
61 | asection *sec; | |
62 | unsigned int size = 0; | |
63 | fragS *frag = segment_info[idx].frag_root; | |
28e4f854 | 64 | |
252b5132 RH |
65 | while (frag) |
66 | { | |
67 | if (frag->fr_address != size) | |
68 | { | |
69 | printf (_("Out of step\n")); | |
70 | size = frag->fr_address; | |
71 | } | |
72 | size += frag->fr_fix; | |
73 | switch (frag->fr_type) | |
74 | { | |
75 | case rs_fill: | |
76 | case rs_org: | |
77 | size += frag->fr_offset * frag->fr_var; | |
78 | break; | |
79 | case rs_align: | |
80 | case rs_align_code: | |
81 | { | |
82 | addressT off; | |
83 | ||
84 | off = relax_align (size, frag->fr_offset); | |
85 | if (frag->fr_subtype != 0 && off > frag->fr_subtype) | |
86 | off = 0; | |
87 | size += off; | |
88 | } | |
89 | } | |
90 | frag = frag->fr_next; | |
91 | } | |
92 | if (size) | |
93 | { | |
94 | char *name = segment_info[idx].name; | |
28e4f854 | 95 | |
252b5132 | 96 | if (name == (char *) NULL) |
28e4f854 KH |
97 | name = ".data"; |
98 | ||
99 | segment_info[idx].user_stuff = | |
100 | (char *) (sec = bfd_make_section (abfd, name)); | |
101 | /* Make it output through itself. */ | |
252b5132 RH |
102 | sec->output_section = sec; |
103 | sec->flags |= SEC_HAS_CONTENTS; | |
104 | bfd_set_section_size (abfd, sec, size); | |
105 | } | |
106 | } | |
107 | ||
28e4f854 KH |
108 | /* Run through a frag chain and write out the data to go with it. */ |
109 | ||
252b5132 | 110 | static void |
1994a7c7 | 111 | fill_section (abfd, idx) |
28e4f854 | 112 | bfd *abfd; |
1994a7c7 | 113 | unsigned int idx; |
252b5132 RH |
114 | { |
115 | asection *sec = segment_info[idx].user_stuff; | |
28e4f854 | 116 | |
252b5132 RH |
117 | if (sec) |
118 | { | |
119 | fragS *frag = segment_info[idx].frag_root; | |
120 | unsigned int offset = 0; | |
121 | while (frag) | |
122 | { | |
123 | unsigned int fill_size; | |
124 | unsigned int count; | |
125 | switch (frag->fr_type) | |
126 | { | |
127 | case rs_fill: | |
128 | case rs_align: | |
129 | case rs_org: | |
130 | if (frag->fr_fix) | |
131 | { | |
132 | bfd_set_section_contents (abfd, | |
133 | sec, | |
134 | frag->fr_literal, | |
135 | frag->fr_address, | |
136 | frag->fr_fix); | |
137 | } | |
138 | offset += frag->fr_fix; | |
139 | fill_size = frag->fr_var; | |
140 | if (fill_size) | |
141 | { | |
142 | unsigned int off = frag->fr_fix; | |
143 | for (count = frag->fr_offset; count; count--) | |
144 | { | |
145 | bfd_set_section_contents (abfd, sec, | |
146 | frag->fr_literal + | |
147 | frag->fr_fix, | |
148 | frag->fr_address + off, | |
149 | fill_size); | |
150 | off += fill_size; | |
151 | } | |
152 | } | |
153 | break; | |
154 | default: | |
155 | abort (); | |
156 | } | |
157 | frag = frag->fr_next; | |
158 | } | |
159 | } | |
160 | } | |
161 | ||
28e4f854 | 162 | /* Count the relocations in a chain. */ |
252b5132 RH |
163 | |
164 | static unsigned int | |
1994a7c7 NC |
165 | count_entries_in_chain (idx) |
166 | unsigned int idx; | |
252b5132 RH |
167 | { |
168 | unsigned int nrelocs; | |
169 | fixS *fixup_ptr; | |
170 | ||
28e4f854 | 171 | /* Count the relocations. */ |
252b5132 RH |
172 | fixup_ptr = segment_info[idx].fix_root; |
173 | nrelocs = 0; | |
174 | while (fixup_ptr != (fixS *) NULL) | |
175 | { | |
176 | fixup_ptr = fixup_ptr->fx_next; | |
177 | nrelocs++; | |
178 | } | |
179 | return nrelocs; | |
180 | } | |
181 | ||
28e4f854 KH |
182 | /* Output all the relocations for a section. */ |
183 | ||
252b5132 | 184 | void |
1994a7c7 NC |
185 | do_relocs_for (idx) |
186 | unsigned int idx; | |
252b5132 RH |
187 | { |
188 | unsigned int nrelocs; | |
189 | arelent **reloc_ptr_vector; | |
190 | arelent *reloc_vector; | |
191 | asymbol **ptrs; | |
192 | asection *section = (asection *) (segment_info[idx].user_stuff); | |
193 | unsigned int i; | |
194 | fixS *from; | |
28e4f854 | 195 | |
252b5132 RH |
196 | if (section) |
197 | { | |
198 | nrelocs = count_entries_in_chain (idx); | |
199 | ||
28e4f854 KH |
200 | reloc_ptr_vector = |
201 | (arelent **) malloc ((nrelocs + 1) * sizeof (arelent *)); | |
252b5132 RH |
202 | reloc_vector = (arelent *) malloc (nrelocs * sizeof (arelent)); |
203 | ptrs = (asymbol **) malloc (nrelocs * sizeof (asymbol *)); | |
204 | from = segment_info[idx].fix_root; | |
205 | for (i = 0; i < nrelocs; i++) | |
206 | { | |
207 | arelent *to = reloc_vector + i; | |
208 | asymbol *s; | |
209 | reloc_ptr_vector[i] = to; | |
210 | to->howto = (reloc_howto_type *) (from->fx_r_type); | |
211 | ||
252b5132 RH |
212 | s = &(from->fx_addsy->sy_symbol.sy); |
213 | to->address = ((char *) (from->fx_frag->fr_address + | |
214 | from->fx_where)) | |
215 | - ((char *) (&(from->fx_frag->fr_literal))); | |
216 | to->addend = from->fx_offset; | |
217 | /* If we know the symbol which we want to relocate to, turn | |
218 | this reloaction into a section relative. | |
219 | ||
220 | If this relocation is pcrelative, and we know the | |
221 | destination, we still want to keep the relocation - since | |
222 | the linker might relax some of the bytes, but it stops | |
28e4f854 | 223 | being pc relative and turns into an absolute relocation. */ |
252b5132 RH |
224 | if (s) |
225 | { | |
226 | if ((s->flags & BSF_UNDEFINED) == 0) | |
227 | { | |
228 | to->section = s->section; | |
229 | ||
230 | /* We can refer directly to the value field here, | |
231 | rather than using S_GET_VALUE, because this is | |
232 | only called after do_symbols, which sets up the | |
233 | value field. */ | |
234 | to->addend += s->value; | |
235 | ||
236 | to->sym_ptr_ptr = 0; | |
237 | if (to->howto->pcrel_offset) | |
28e4f854 KH |
238 | /* This is a pcrel relocation, the addend should |
239 | be adjusted. */ | |
240 | to->addend -= to->address + 1; | |
252b5132 RH |
241 | } |
242 | else | |
243 | { | |
244 | to->section = 0; | |
245 | *ptrs = &(from->fx_addsy->sy_symbol.sy); | |
246 | to->sym_ptr_ptr = ptrs; | |
247 | ||
248 | if (to->howto->pcrel_offset) | |
28e4f854 KH |
249 | /* This is a pcrel relocation, the addend should |
250 | be adjusted. */ | |
251 | to->addend -= to->address - 1; | |
252b5132 | 252 | } |
252b5132 RH |
253 | } |
254 | else | |
28e4f854 | 255 | to->section = 0; |
252b5132 RH |
256 | |
257 | ptrs++; | |
258 | from = from->fx_next; | |
259 | } | |
260 | ||
aaa2624b | 261 | /* Attach to the section. */ |
252b5132 RH |
262 | section->orelocation = reloc_ptr_vector; |
263 | section->reloc_count = nrelocs; | |
264 | section->flags |= SEC_LOAD; | |
265 | } | |
266 | } | |
267 | ||
28e4f854 KH |
268 | /* Do the symbols. */ |
269 | ||
252b5132 | 270 | static void |
1994a7c7 | 271 | do_symbols (abfd) |
28e4f854 | 272 | bfd *abfd; |
252b5132 RH |
273 | { |
274 | extern symbolS *symbol_rootP; | |
275 | symbolS *ptr; | |
276 | asymbol **symbol_ptr_vec; | |
277 | asymbol *symbol_vec; | |
278 | unsigned int count = 0; | |
279 | unsigned int index; | |
280 | ||
252b5132 RH |
281 | for (ptr = symbol_rootP; |
282 | ptr != (symbolS *) NULL; | |
283 | ptr = ptr->sy_next) | |
284 | { | |
285 | if (SEG_NORMAL (ptr->sy_symbol.seg)) | |
286 | { | |
287 | ptr->sy_symbol.sy.section = | |
288 | (asection *) (segment_info[ptr->sy_symbol.seg].user_stuff); | |
ac62c346 | 289 | S_SET_VALUE (ptr, S_GET_VALUE (ptr)); |
252b5132 | 290 | if (ptr->sy_symbol.sy.flags == 0) |
28e4f854 | 291 | ptr->sy_symbol.sy.flags = BSF_LOCAL; |
252b5132 RH |
292 | } |
293 | else | |
294 | { | |
295 | switch (ptr->sy_symbol.seg) | |
296 | { | |
297 | case SEG_ABSOLUTE: | |
298 | ptr->sy_symbol.sy.flags |= BSF_ABSOLUTE; | |
299 | ptr->sy_symbol.sy.section = 0; | |
300 | break; | |
301 | case SEG_UNKNOWN: | |
302 | ptr->sy_symbol.sy.flags = BSF_UNDEFINED; | |
303 | ptr->sy_symbol.sy.section = 0; | |
304 | break; | |
305 | default: | |
306 | abort (); | |
307 | } | |
308 | } | |
309 | ptr->sy_symbol.sy.value = S_GET_VALUE (ptr); | |
310 | count++; | |
311 | } | |
312 | symbol_ptr_vec = (asymbol **) malloc ((count + 1) * sizeof (asymbol *)); | |
313 | ||
314 | index = 0; | |
315 | for (ptr = symbol_rootP; | |
316 | ptr != (symbolS *) NULL; | |
317 | ptr = ptr->sy_next) | |
318 | { | |
319 | symbol_ptr_vec[index] = &(ptr->sy_symbol.sy); | |
320 | index++; | |
321 | } | |
322 | symbol_ptr_vec[index] = 0; | |
323 | abfd->outsymbols = symbol_ptr_vec; | |
324 | abfd->symcount = count; | |
325 | } | |
326 | ||
327 | /* The generic as->bfd converter. Other backends may have special case | |
28e4f854 | 328 | code. */ |
252b5132 RH |
329 | |
330 | void | |
1994a7c7 | 331 | bfd_as_write_hook () |
252b5132 RH |
332 | { |
333 | int i; | |
334 | ||
335 | for (i = SEG_E0; i < SEG_UNKNOWN; i++) | |
28e4f854 | 336 | size_section (abfd, i); |
252b5132 RH |
337 | |
338 | for (i = SEG_E0; i < SEG_UNKNOWN; i++) | |
339 | fill_section (abfd, i); | |
340 | ||
341 | do_symbols (abfd); | |
342 | ||
343 | for (i = SEG_E0; i < SEG_UNKNOWN; i++) | |
344 | do_relocs_for (i); | |
252b5132 RH |
345 | } |
346 | ||
347 | S_SET_SEGMENT (x, y) | |
348 | symbolS *x; | |
349 | int y; | |
350 | { | |
351 | x->sy_symbol.seg = y; | |
352 | } | |
353 | ||
354 | S_IS_DEFINED (x) | |
355 | symbolS *x; | |
356 | { | |
357 | if (SEG_NORMAL (x->sy_symbol.seg)) | |
358 | { | |
359 | return 1; | |
360 | } | |
361 | switch (x->sy_symbol.seg) | |
362 | { | |
363 | case SEG_UNKNOWN: | |
364 | return 0; | |
365 | default: | |
366 | abort (); | |
367 | } | |
368 | } | |
369 | ||
370 | S_IS_EXTERNAL (x) | |
371 | { | |
372 | abort (); | |
373 | } | |
374 | ||
375 | S_GET_DESC (x) | |
376 | { | |
377 | abort (); | |
378 | } | |
379 | ||
380 | S_GET_SEGMENT (x) | |
381 | symbolS *x; | |
382 | { | |
383 | return x->sy_symbol.seg; | |
384 | } | |
385 | ||
386 | S_SET_EXTERNAL (x) | |
387 | symbolS *x; | |
388 | { | |
389 | x->sy_symbol.sy.flags |= BSF_GLOBAL | BSF_EXPORT; | |
390 | } | |
391 | ||
392 | S_SET_NAME (x, y) | |
393 | symbolS *x; | |
394 | char *y; | |
395 | { | |
396 | x->sy_symbol.sy.name = y; | |
397 | } | |
398 | ||
399 | S_GET_OTHER (x) | |
400 | { | |
401 | abort (); | |
402 | } | |
403 | ||
404 | S_IS_DEBUG (x) | |
405 | { | |
406 | abort (); | |
407 | } | |
408 | ||
409 | #ifndef segment_name | |
410 | char * | |
411 | segment_name () | |
412 | { | |
413 | abort (); | |
414 | } | |
415 | #endif | |
416 | ||
417 | void | |
418 | obj_read_begin_hook () | |
419 | { | |
420 | } | |
421 | ||
422 | static void | |
423 | obj_ieee_section (ignore) | |
424 | int ignore; | |
425 | { | |
426 | extern char *input_line_pointer; | |
427 | extern char is_end_of_line[]; | |
428 | char *p = input_line_pointer; | |
429 | char *s = p; | |
430 | int i; | |
28e4f854 KH |
431 | |
432 | /* Look up the name, if it doesn't exist, make it. */ | |
252b5132 RH |
433 | while (*p && *p != ' ' && *p != ',' && !is_end_of_line[*p]) |
434 | { | |
435 | p++; | |
436 | } | |
437 | for (i = SEG_E0; i < SEG_UNKNOWN; i++) | |
438 | { | |
439 | if (segment_info[i].hadone) | |
440 | { | |
441 | if (strncmp (segment_info[i].name, s, p - s) == 0) | |
28e4f854 | 442 | goto ok; |
252b5132 RH |
443 | } |
444 | else | |
445 | break; | |
446 | } | |
447 | if (i == SEG_UNKNOWN) | |
448 | { | |
449 | as_bad (_("too many sections")); | |
450 | return; | |
451 | } | |
452 | ||
453 | segment_info[i].hadone = 1; | |
454 | segment_info[i].name = malloc (p - s + 1); | |
455 | memcpy (segment_info[i].name, s, p - s); | |
456 | segment_info[i].name[p - s] = 0; | |
457 | ok: | |
458 | subseg_set (i, 0); | |
459 | while (!is_end_of_line[*p]) | |
460 | p++; | |
461 | input_line_pointer = p; | |
252b5132 RH |
462 | } |
463 | ||
252b5132 RH |
464 | const pseudo_typeS obj_pseudo_table[] = |
465 | { | |
466 | {"section", obj_ieee_section, 0}, | |
28e4f854 KH |
467 | {"data.b" , cons , 1}, |
468 | {"data.w" , cons , 2}, | |
469 | {"data.l" , cons , 4}, | |
470 | {"export" , s_globl , 0}, | |
471 | {"option" , s_ignore , 0}, | |
472 | {"end" , s_ignore , 0}, | |
473 | {"import" , s_ignore , 0}, | |
474 | {"sdata" , stringer , 0}, | |
252b5132 | 475 | 0, |
252b5132 RH |
476 | }; |
477 | ||
252b5132 RH |
478 | void |
479 | obj_symbol_new_hook (symbolP) | |
480 | symbolS *symbolP; | |
481 | { | |
482 | symbolP->sy_symbol.sy.the_bfd = abfd; | |
483 | } | |
484 | ||
252b5132 | 485 | #if 1 |
18e1d487 AM |
486 | |
487 | #ifndef SUB_SEGMENT_ALIGN | |
488 | #ifdef HANDLE_ALIGN | |
aaa2624b | 489 | /* The last subsegment gets an alignment corresponding to the alignment |
18e1d487 AM |
490 | of the section. This allows proper nop-filling at the end of |
491 | code-bearing sections. */ | |
492 | #define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) \ | |
493 | (!(FRCHAIN)->frch_next || (FRCHAIN)->frch_next->frch_seg != (SEG) \ | |
494 | ? get_recorded_alignment (SEG) : 0) | |
495 | #else | |
496 | #define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) 2 | |
497 | #endif | |
498 | #endif | |
499 | ||
252b5132 | 500 | extern void |
1994a7c7 | 501 | write_object_file () |
252b5132 RH |
502 | { |
503 | int i; | |
504 | struct frchain *frchain_ptr; | |
505 | struct frag *frag_ptr; | |
506 | ||
507 | abfd = bfd_openw (out_file_name, "ieee"); | |
508 | ||
509 | if (abfd == 0) | |
510 | { | |
511 | as_perror (_("FATAL: Can't create %s"), out_file_name); | |
512 | exit (EXIT_FAILURE); | |
513 | } | |
514 | bfd_set_format (abfd, bfd_object); | |
515 | bfd_set_arch_mach (abfd, bfd_arch_h8300, 0); | |
516 | subseg_set (1, 0); | |
517 | subseg_set (2, 0); | |
518 | subseg_set (3, 0); | |
18e1d487 AM |
519 | |
520 | /* Run through all the sub-segments and align them up. Also | |
521 | close any open frags. We tack a .fill onto the end of the | |
522 | frag chain so that any .align's size can be worked by looking | |
523 | at the next frag. */ | |
252b5132 RH |
524 | for (frchain_ptr = frchain_root; |
525 | frchain_ptr != (struct frchain *) NULL; | |
526 | frchain_ptr = frchain_ptr->frch_next) | |
527 | { | |
18e1d487 | 528 | int alignment; |
252b5132 RH |
529 | |
530 | subseg_set (frchain_ptr->frch_seg, frchain_ptr->frch_subseg); | |
18e1d487 AM |
531 | |
532 | alignment = SUB_SEGMENT_ALIGN (now_seg, frchain_ptr) | |
533 | ||
534 | #ifdef md_do_align | |
535 | md_do_align (alignment, (char *) NULL, 0, 0, alignment_done); | |
536 | #endif | |
537 | if (subseg_text_p (now_seg)) | |
538 | frag_align_code (alignment, 0); | |
539 | else | |
540 | frag_align (alignment, 0, 0); | |
541 | ||
542 | #ifdef md_do_align | |
543 | alignment_done: | |
252b5132 | 544 | #endif |
18e1d487 | 545 | |
252b5132 RH |
546 | frag_wane (frag_now); |
547 | frag_now->fr_fix = 0; | |
548 | know (frag_now->fr_next == NULL); | |
549 | } | |
550 | ||
551 | /* Now build one big frag chain for each segment, linked through | |
28e4f854 | 552 | fr_next. */ |
252b5132 RH |
553 | for (i = SEG_E0; i < SEG_UNKNOWN; i++) |
554 | { | |
252b5132 RH |
555 | fragS **prev_frag_ptr_ptr; |
556 | struct frchain *next_frchain_ptr; | |
557 | ||
252b5132 | 558 | segment_info[i].frag_root = segment_info[i].frchainP->frch_root; |
252b5132 RH |
559 | } |
560 | ||
561 | for (i = SEG_E0; i < SEG_UNKNOWN; i++) | |
28e4f854 | 562 | relax_segment (segment_info[i].frag_root, i); |
252b5132 | 563 | |
1cd55018 AM |
564 | /* Relaxation has completed. Freeze all syms. */ |
565 | finalize_syms = 1; | |
566 | ||
28e4f854 | 567 | /* Now the addresses of the frags are correct within the segment. */ |
252b5132 RH |
568 | |
569 | bfd_as_write_hook (); | |
570 | bfd_close (abfd); | |
571 | } | |
572 | ||
573 | #endif | |
574 | ||
575 | H_SET_TEXT_SIZE (a, b) | |
576 | { | |
577 | abort (); | |
578 | } | |
579 | ||
580 | H_GET_TEXT_SIZE () | |
581 | { | |
582 | abort (); | |
583 | } | |
584 | ||
585 | H_SET_BSS_SIZE () | |
586 | { | |
587 | abort (); | |
588 | } | |
589 | ||
590 | H_SET_STRING_SIZE () | |
591 | { | |
592 | abort (); | |
593 | } | |
594 | ||
595 | H_SET_RELOCATION_SIZE () | |
596 | { | |
597 | abort (); | |
598 | } | |
599 | ||
600 | H_SET_MAGIC_NUMBER () | |
601 | { | |
602 | abort (); | |
603 | } | |
604 | ||
605 | H_GET_FILE_SIZE () | |
606 | { | |
607 | abort (); | |
608 | } | |
609 | ||
610 | H_GET_TEXT_RELOCATION_SIZE () | |
611 | { | |
612 | abort (); | |
613 | } |