source: trunk/binutils/gas/config/obj-ieee.c@ 2562

Last change on this file since 2562 was 610, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r609,
which included commits to RCS files with non-trunk default branches.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 13.1 KB
Line 
1/* obj-format for ieee-695 records.
2 Copyright 1991, 1992, 1993, 1994, 1997, 2000
3 Free Software Foundation, Inc.
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
19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA. */
21
22/* Created by Steve Chamberlain <steve@cygnus.com>. */
23
24/* This will hopefully become the port through which bfd and gas talk,
25 for the moment, only ieee is known to work well. */
26
27#include "bfd.h"
28#include "as.h"
29#include "subsegs.h"
30#include "output-file.h"
31#include "frags.h"
32
33bfd *abfd;
34
35/* How many addresses does the .align take? */
36
37static relax_addressT
38relax_align (address, alignment)
39 /* Address now. */
40 register relax_addressT address;
41
42 /* Alignment (binary). */
43 register long alignment;
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);
51}
52
53/* Calculate the size of the frag chain
54 and create a bfd section to contain all of it. */
55
56static void
57size_section (abfd, idx)
58 bfd *abfd;
59 unsigned int idx;
60{
61 asection *sec;
62 unsigned int size = 0;
63 fragS *frag = segment_info[idx].frag_root;
64
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;
95
96 if (name == (char *) NULL)
97 name = ".data";
98
99 segment_info[idx].user_stuff =
100 (char *) (sec = bfd_make_section (abfd, name));
101 /* Make it output through itself. */
102 sec->output_section = sec;
103 sec->flags |= SEC_HAS_CONTENTS;
104 bfd_set_section_size (abfd, sec, size);
105 }
106}
107
108/* Run through a frag chain and write out the data to go with it. */
109
110static void
111fill_section (abfd, idx)
112 bfd *abfd;
113 unsigned int idx;
114{
115 asection *sec = segment_info[idx].user_stuff;
116
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
162/* Count the relocations in a chain. */
163
164static unsigned int
165count_entries_in_chain (idx)
166 unsigned int idx;
167{
168 unsigned int nrelocs;
169 fixS *fixup_ptr;
170
171 /* Count the relocations. */
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
182/* Output all the relocations for a section. */
183
184void
185do_relocs_for (idx)
186 unsigned int idx;
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;
195
196 if (section)
197 {
198 nrelocs = count_entries_in_chain (idx);
199
200 reloc_ptr_vector =
201 (arelent **) malloc ((nrelocs + 1) * sizeof (arelent *));
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
212#if 0
213 /* We can't represent complicated things in a reloc yet. */
214 if (from->fx_addsy == 0 || from->fx_subsy != 0)
215 abort ();
216#endif
217
218 s = &(from->fx_addsy->sy_symbol.sy);
219 to->address = ((char *) (from->fx_frag->fr_address +
220 from->fx_where))
221 - ((char *) (&(from->fx_frag->fr_literal)));
222 to->addend = from->fx_offset;
223 /* If we know the symbol which we want to relocate to, turn
224 this reloaction into a section relative.
225
226 If this relocation is pcrelative, and we know the
227 destination, we still want to keep the relocation - since
228 the linker might relax some of the bytes, but it stops
229 being pc relative and turns into an absolute relocation. */
230 if (s)
231 {
232 if ((s->flags & BSF_UNDEFINED) == 0)
233 {
234 to->section = s->section;
235
236 /* We can refer directly to the value field here,
237 rather than using S_GET_VALUE, because this is
238 only called after do_symbols, which sets up the
239 value field. */
240 to->addend += s->value;
241
242 to->sym_ptr_ptr = 0;
243 if (to->howto->pcrel_offset)
244 /* This is a pcrel relocation, the addend should
245 be adjusted. */
246 to->addend -= to->address + 1;
247 }
248 else
249 {
250 to->section = 0;
251 *ptrs = &(from->fx_addsy->sy_symbol.sy);
252 to->sym_ptr_ptr = ptrs;
253
254 if (to->howto->pcrel_offset)
255 /* This is a pcrel relocation, the addend should
256 be adjusted. */
257 to->addend -= to->address - 1;
258 }
259 }
260 else
261 to->section = 0;
262
263 ptrs++;
264 from = from->fx_next;
265 }
266
267 /* Attatch to the section. */
268 section->orelocation = reloc_ptr_vector;
269 section->reloc_count = nrelocs;
270 section->flags |= SEC_LOAD;
271 }
272}
273
274/* Do the symbols. */
275
276static void
277do_symbols (abfd)
278 bfd *abfd;
279{
280 extern symbolS *symbol_rootP;
281 symbolS *ptr;
282 asymbol **symbol_ptr_vec;
283 asymbol *symbol_vec;
284 unsigned int count = 0;
285 unsigned int index;
286
287 for (ptr = symbol_rootP;
288 ptr != (symbolS *) NULL;
289 ptr = ptr->sy_next)
290 {
291 if (SEG_NORMAL (ptr->sy_symbol.seg))
292 {
293 ptr->sy_symbol.sy.section =
294 (asection *) (segment_info[ptr->sy_symbol.seg].user_stuff);
295 S_SET_VALUE (ptr, S_GET_VALUE (ptr));
296 if (ptr->sy_symbol.sy.flags == 0)
297 ptr->sy_symbol.sy.flags = BSF_LOCAL;
298 }
299 else
300 {
301 switch (ptr->sy_symbol.seg)
302 {
303 case SEG_ABSOLUTE:
304 ptr->sy_symbol.sy.flags |= BSF_ABSOLUTE;
305 ptr->sy_symbol.sy.section = 0;
306 break;
307 case SEG_UNKNOWN:
308 ptr->sy_symbol.sy.flags = BSF_UNDEFINED;
309 ptr->sy_symbol.sy.section = 0;
310 break;
311 default:
312 abort ();
313 }
314 }
315 ptr->sy_symbol.sy.value = S_GET_VALUE (ptr);
316 count++;
317 }
318 symbol_ptr_vec = (asymbol **) malloc ((count + 1) * sizeof (asymbol *));
319
320 index = 0;
321 for (ptr = symbol_rootP;
322 ptr != (symbolS *) NULL;
323 ptr = ptr->sy_next)
324 {
325 symbol_ptr_vec[index] = &(ptr->sy_symbol.sy);
326 index++;
327 }
328 symbol_ptr_vec[index] = 0;
329 abfd->outsymbols = symbol_ptr_vec;
330 abfd->symcount = count;
331}
332
333/* The generic as->bfd converter. Other backends may have special case
334 code. */
335
336void
337bfd_as_write_hook ()
338{
339 int i;
340
341 for (i = SEG_E0; i < SEG_UNKNOWN; i++)
342 size_section (abfd, i);
343
344 for (i = SEG_E0; i < SEG_UNKNOWN; i++)
345 fill_section (abfd, i);
346
347 do_symbols (abfd);
348
349 for (i = SEG_E0; i < SEG_UNKNOWN; i++)
350 do_relocs_for (i);
351}
352
353S_SET_SEGMENT (x, y)
354 symbolS *x;
355 int y;
356{
357 x->sy_symbol.seg = y;
358}
359
360S_IS_DEFINED (x)
361 symbolS *x;
362{
363 if (SEG_NORMAL (x->sy_symbol.seg))
364 {
365 return 1;
366 }
367 switch (x->sy_symbol.seg)
368 {
369 case SEG_UNKNOWN:
370 return 0;
371 default:
372 abort ();
373 }
374}
375
376S_IS_EXTERNAL (x)
377{
378 abort ();
379}
380
381S_GET_DESC (x)
382{
383 abort ();
384}
385
386S_GET_SEGMENT (x)
387 symbolS *x;
388{
389 return x->sy_symbol.seg;
390}
391
392S_SET_EXTERNAL (x)
393 symbolS *x;
394{
395 x->sy_symbol.sy.flags |= BSF_GLOBAL | BSF_EXPORT;
396}
397
398S_SET_NAME (x, y)
399 symbolS *x;
400 char *y;
401{
402 x->sy_symbol.sy.name = y;
403}
404
405S_GET_OTHER (x)
406{
407 abort ();
408}
409
410S_IS_DEBUG (x)
411{
412 abort ();
413}
414
415#ifndef segment_name
416char *
417segment_name ()
418{
419 abort ();
420}
421#endif
422
423void
424obj_read_begin_hook ()
425{
426}
427
428static void
429obj_ieee_section (ignore)
430 int ignore;
431{
432 extern char *input_line_pointer;
433 extern char is_end_of_line[];
434 char *p = input_line_pointer;
435 char *s = p;
436 int i;
437
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 goto ok;
449 }
450 else
451 break;
452 }
453 if (i == SEG_UNKNOWN)
454 {
455 as_bad (_("too many sections"));
456 return;
457 }
458
459 segment_info[i].hadone = 1;
460 segment_info[i].name = malloc (p - s + 1);
461 memcpy (segment_info[i].name, s, p - s);
462 segment_info[i].name[p - s] = 0;
463ok:
464 subseg_set (i, 0);
465 while (!is_end_of_line[*p])
466 p++;
467 input_line_pointer = p;
468}
469
470void cons ();
471void s_ignore ();
472
473void s_globl ();
474const pseudo_typeS obj_pseudo_table[] =
475{
476 {"section", obj_ieee_section, 0},
477 {"data.b" , cons , 1},
478 {"data.w" , cons , 2},
479 {"data.l" , cons , 4},
480 {"export" , s_globl , 0},
481 {"option" , s_ignore , 0},
482 {"end" , s_ignore , 0},
483 {"import" , s_ignore , 0},
484 {"sdata" , stringer , 0},
485 0,
486};
487
488void
489obj_symbol_new_hook (symbolP)
490 symbolS *symbolP;
491{
492 symbolP->sy_symbol.sy.the_bfd = abfd;
493}
494
495#if 1
496
497#ifndef SUB_SEGMENT_ALIGN
498#ifdef HANDLE_ALIGN
499/* The last subsegment gets an aligment corresponding to the alignment
500 of the section. This allows proper nop-filling at the end of
501 code-bearing sections. */
502#define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) \
503 (!(FRCHAIN)->frch_next || (FRCHAIN)->frch_next->frch_seg != (SEG) \
504 ? get_recorded_alignment (SEG) : 0)
505#else
506#define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) 2
507#endif
508#endif
509
510extern void
511write_object_file ()
512{
513 int i;
514 struct frchain *frchain_ptr;
515 struct frag *frag_ptr;
516
517 abfd = bfd_openw (out_file_name, "ieee");
518
519 if (abfd == 0)
520 {
521 as_perror (_("FATAL: Can't create %s"), out_file_name);
522 exit (EXIT_FAILURE);
523 }
524 bfd_set_format (abfd, bfd_object);
525 bfd_set_arch_mach (abfd, bfd_arch_h8300, 0);
526 subseg_set (1, 0);
527 subseg_set (2, 0);
528 subseg_set (3, 0);
529
530 /* Run through all the sub-segments and align them up. Also
531 close any open frags. We tack a .fill onto the end of the
532 frag chain so that any .align's size can be worked by looking
533 at the next frag. */
534 for (frchain_ptr = frchain_root;
535 frchain_ptr != (struct frchain *) NULL;
536 frchain_ptr = frchain_ptr->frch_next)
537 {
538 int alignment;
539
540 subseg_set (frchain_ptr->frch_seg, frchain_ptr->frch_subseg);
541
542 alignment = SUB_SEGMENT_ALIGN (now_seg, frchain_ptr)
543
544#ifdef md_do_align
545 md_do_align (alignment, (char *) NULL, 0, 0, alignment_done);
546#endif
547 if (subseg_text_p (now_seg))
548 frag_align_code (alignment, 0);
549 else
550 frag_align (alignment, 0, 0);
551
552#ifdef md_do_align
553 alignment_done:
554#endif
555
556 frag_wane (frag_now);
557 frag_now->fr_fix = 0;
558 know (frag_now->fr_next == NULL);
559 }
560
561 /* Now build one big frag chain for each segment, linked through
562 fr_next. */
563 for (i = SEG_E0; i < SEG_UNKNOWN; i++)
564 {
565 fragS **prev_frag_ptr_ptr;
566 struct frchain *next_frchain_ptr;
567
568#if 0
569 struct frag **head_ptr = segment_info[i].frag_root;
570#endif
571
572 segment_info[i].frag_root = segment_info[i].frchainP->frch_root;
573#if 0
574 /* I'm not sure what this is for. */
575 for (frchain_ptr = segment_info[i].frchainP->frch_root;
576 frchain_ptr != (struct frchain *) NULL;
577 frchain_ptr = frchain_ptr->frch_next)
578 {
579 *head_ptr = frchain_ptr;
580 head_ptr = &frchain_ptr->next;
581 }
582#endif
583 }
584
585 for (i = SEG_E0; i < SEG_UNKNOWN; i++)
586 relax_segment (segment_info[i].frag_root, i);
587
588 /* Relaxation has completed. Freeze all syms. */
589 finalize_syms = 1;
590
591 /* Now the addresses of the frags are correct within the segment. */
592
593 bfd_as_write_hook ();
594 bfd_close (abfd);
595}
596
597#endif
598
599H_SET_TEXT_SIZE (a, b)
600{
601 abort ();
602}
603
604H_GET_TEXT_SIZE ()
605{
606 abort ();
607}
608
609H_SET_BSS_SIZE ()
610{
611 abort ();
612}
613
614H_SET_STRING_SIZE ()
615{
616 abort ();
617}
618
619H_SET_RELOCATION_SIZE ()
620{
621 abort ();
622}
623
624H_SET_MAGIC_NUMBER ()
625{
626 abort ();
627}
628
629H_GET_FILE_SIZE ()
630{
631 abort ();
632}
633
634H_GET_TEXT_RELOCATION_SIZE ()
635{
636 abort ();
637}
Note: See TracBrowser for help on using the repository browser.