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