Commit | Line | Data |
---|---|---|
cd8761e1 | 1 | /* obj-format for ieee-695 records. |
48401fcf | 2 | Copyright (C) 1991, 92, 93, 94, 95, 1997, 1998 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 steve@cygnus.com |
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 | { | |
48401fcf | 69 | printf (_("Out of step\n")); |
355afbcd | 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 | |
7cad1a89 | 418 | #ifndef segment_name |
355afbcd KR |
419 | char * |
420 | segment_name () | |
421 | { | |
422 | abort (); | |
423 | } | |
7cad1a89 | 424 | #endif |
cd8761e1 | 425 | |
355afbcd KR |
426 | void |
427 | obj_read_begin_hook () | |
428 | { | |
429 | } | |
cd8761e1 | 430 | |
355afbcd KR |
431 | static void |
432 | obj_ieee_section (ignore) | |
433 | int ignore; | |
cd8761e1 | 434 | { |
355afbcd KR |
435 | extern char *input_line_pointer; |
436 | extern char is_end_of_line[]; | |
437 | char *p = input_line_pointer; | |
438 | char *s = p; | |
439 | int i; | |
440 | /* Look up the name, if it doesn't exist, make it */ | |
441 | while (*p && *p != ' ' && *p != ',' && !is_end_of_line[*p]) | |
442 | { | |
443 | p++; | |
444 | } | |
445 | for (i = SEG_E0; i < SEG_UNKNOWN; i++) | |
446 | { | |
447 | if (segment_info[i].hadone) | |
448 | { | |
449 | if (strncmp (segment_info[i].name, s, p - s) == 0) | |
450 | { | |
451 | goto ok; | |
452 | ||
453 | } | |
a39116f1 | 454 | } |
355afbcd KR |
455 | else |
456 | break; | |
457 | } | |
458 | if (i == SEG_UNKNOWN) | |
459 | { | |
48401fcf | 460 | as_bad (_("too many sections")); |
355afbcd KR |
461 | return; |
462 | } | |
463 | ||
464 | segment_info[i].hadone = 1; | |
465 | segment_info[i].name = malloc (p - s + 1); | |
466 | memcpy (segment_info[i].name, s, p - s); | |
467 | segment_info[i].name[p - s] = 0; | |
468 | ok: | |
604633ae | 469 | subseg_set (i, 0); |
355afbcd KR |
470 | while (!is_end_of_line[*p]) |
471 | p++; | |
472 | input_line_pointer = p; | |
473 | ||
cd8761e1 SC |
474 | } |
475 | ||
476 | ||
355afbcd KR |
477 | void cons (); |
478 | void s_ignore (); | |
cd8761e1 SC |
479 | |
480 | ||
355afbcd KR |
481 | void s_globl (); |
482 | const pseudo_typeS obj_pseudo_table[] = | |
483 | { | |
484 | {"section", obj_ieee_section, 0}, | |
485 | {"data.b", cons, 1}, | |
486 | {"data.w", cons, 2}, | |
487 | {"data.l", cons, 4}, | |
488 | {"export", s_globl, 0}, | |
489 | {"option", s_ignore, 0}, | |
490 | {"end", s_ignore, 0}, | |
491 | {"import", s_ignore, 0}, | |
492 | {"sdata", stringer, 0}, | |
493 | 0, | |
494 | ||
cd8761e1 SC |
495 | }; |
496 | ||
497 | ||
498 | ||
355afbcd KR |
499 | void |
500 | obj_symbol_new_hook (symbolP) | |
501 | symbolS *symbolP; | |
cd8761e1 | 502 | { |
355afbcd | 503 | symbolP->sy_symbol.sy.the_bfd = abfd; |
cd8761e1 SC |
504 | } |
505 | ||
506 | ||
507 | ||
508 | ||
509 | ||
510 | #if 1 | |
355afbcd KR |
511 | extern void |
512 | DEFUN_VOID (write_object_file) | |
513 | { | |
514 | int i; | |
515 | struct frchain *frchain_ptr; | |
516 | struct frag *frag_ptr; | |
517 | ||
518 | abfd = bfd_openw (out_file_name, "ieee"); | |
519 | ||
520 | if (abfd == 0) | |
521 | { | |
48401fcf | 522 | as_perror (_("FATAL: Can't create %s"), out_file_name); |
460531da | 523 | exit (EXIT_FAILURE); |
355afbcd KR |
524 | } |
525 | bfd_set_format (abfd, bfd_object); | |
526 | bfd_set_arch_mach (abfd, bfd_arch_h8300, 0); | |
604633ae ILT |
527 | subseg_set (1, 0); |
528 | subseg_set (2, 0); | |
529 | subseg_set (3, 0); | |
355afbcd KR |
530 | for (frchain_ptr = frchain_root; |
531 | frchain_ptr != (struct frchain *) NULL; | |
532 | frchain_ptr = frchain_ptr->frch_next) | |
533 | { | |
534 | /* Run through all the sub-segments and align them up. Also close any | |
2492e118 KR |
535 | open frags. We tack a .fill onto the end of the frag chain so |
536 | that any .align's size can be worked by looking at the next | |
537 | frag. */ | |
355afbcd | 538 | |
604633ae | 539 | subseg_set (frchain_ptr->frch_seg, frchain_ptr->frch_subseg); |
3eb802b5 | 540 | #ifndef SUB_SEGMENT_ALIGN |
2492e118 | 541 | #define SUB_SEGMENT_ALIGN(SEG) 2 |
3eb802b5 | 542 | #endif |
d7bf6158 | 543 | frag_align (SUB_SEGMENT_ALIGN (now_seg), 0, 0); |
355afbcd KR |
544 | frag_wane (frag_now); |
545 | frag_now->fr_fix = 0; | |
546 | know (frag_now->fr_next == NULL); | |
547 | } | |
548 | ||
549 | /* Now build one big frag chain for each segment, linked through | |
a39116f1 | 550 | fr_next. */ |
355afbcd KR |
551 | for (i = SEG_E0; i < SEG_UNKNOWN; i++) |
552 | { | |
553 | ||
554 | fragS **prev_frag_ptr_ptr; | |
555 | struct frchain *next_frchain_ptr; | |
556 | ||
557 | /* struct frag **head_ptr = segment_info[i].frag_root;*/ | |
558 | ||
559 | segment_info[i].frag_root = segment_info[i].frchainP->frch_root; | |
cd8761e1 | 560 | #if 0 |
355afbcd KR |
561 | /* Im not sure what this is for */ |
562 | for (frchain_ptr = segment_info[i].frchainP->frch_root; | |
563 | frchain_ptr != (struct frchain *) NULL; | |
564 | frchain_ptr = frchain_ptr->frch_next) | |
565 | { | |
566 | *head_ptr = frchain_ptr; | |
567 | head_ptr = &frchain_ptr->next; | |
a39116f1 | 568 | } |
355afbcd KR |
569 | |
570 | ||
571 | #endif | |
572 | } | |
573 | ||
574 | for (i = SEG_E0; i < SEG_UNKNOWN; i++) | |
575 | { | |
576 | relax_segment (segment_info[i].frag_root, i); | |
577 | } | |
578 | ||
579 | /* Now the addresses of the frags are correct within the segment */ | |
580 | ||
581 | bfd_as_write_hook (); | |
582 | bfd_close (abfd); | |
cd8761e1 SC |
583 | } |
584 | ||
585 | #endif | |
586 | ||
355afbcd KR |
587 | H_SET_TEXT_SIZE (a, b) |
588 | { | |
589 | abort (); | |
590 | } | |
591 | ||
592 | H_GET_TEXT_SIZE () | |
593 | { | |
594 | abort (); | |
595 | } | |
596 | ||
597 | H_SET_BSS_SIZE () | |
598 | { | |
599 | abort (); | |
600 | } | |
601 | ||
602 | H_SET_STRING_SIZE () | |
603 | { | |
604 | abort (); | |
605 | } | |
606 | ||
607 | H_SET_RELOCATION_SIZE () | |
608 | { | |
609 | abort (); | |
610 | } | |
611 | ||
612 | H_SET_MAGIC_NUMBER () | |
613 | { | |
614 | abort (); | |
615 | } | |
616 | ||
617 | H_GET_FILE_SIZE () | |
618 | { | |
619 | abort (); | |
620 | } | |
621 | ||
622 | H_GET_TEXT_RELOCATION_SIZE () | |
623 | { | |
624 | abort (); | |
625 | } | |
a39116f1 RP |
626 | |
627 | /* end of obj-ieee.c */ |