Merge from vendor branch OPENSSH:
[dragonfly.git] / contrib / binutils / gas / config / obj-ieee.c
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
33 bfd *abfd;
34
35 /* How many addresses does the .align take?  */
36
37 static relax_addressT
38 relax_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
56 static void
57 size_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
110 static void
111 fill_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
164 static unsigned int
165 count_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
184 void
185 do_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
276 static void
277 do_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
336 void
337 bfd_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
353 S_SET_SEGMENT (x, y)
354      symbolS *x;
355      int y;
356 {
357   x->sy_symbol.seg = y;
358 }
359
360 S_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
376 S_IS_EXTERNAL (x)
377 {
378   abort ();
379 }
380
381 S_GET_DESC (x)
382 {
383   abort ();
384 }
385
386 S_GET_SEGMENT (x)
387      symbolS *x;
388 {
389   return x->sy_symbol.seg;
390 }
391
392 S_SET_EXTERNAL (x)
393      symbolS *x;
394 {
395   x->sy_symbol.sy.flags |= BSF_GLOBAL | BSF_EXPORT;
396 }
397
398 S_SET_NAME (x, y)
399      symbolS *x;
400      char *y;
401 {
402   x->sy_symbol.sy.name = y;
403 }
404
405 S_GET_OTHER (x)
406 {
407   abort ();
408 }
409
410 S_IS_DEBUG (x)
411 {
412   abort ();
413 }
414
415 #ifndef segment_name
416 char *
417 segment_name ()
418 {
419   abort ();
420 }
421 #endif
422
423 void
424 obj_read_begin_hook ()
425 {
426 }
427
428 static void
429 obj_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;
463 ok:
464   subseg_set (i, 0);
465   while (!is_end_of_line[*p])
466     p++;
467   input_line_pointer = p;
468 }
469
470 void cons ();
471 void s_ignore ();
472
473 void s_globl ();
474 const 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
488 void
489 obj_symbol_new_hook (symbolP)
490      symbolS *symbolP;
491 {
492   symbolP->sy_symbol.sy.the_bfd = abfd;
493 }
494
495 #if 1
496 extern void
497 write_object_file ()
498 {
499   int i;
500   struct frchain *frchain_ptr;
501   struct frag *frag_ptr;
502
503   abfd = bfd_openw (out_file_name, "ieee");
504
505   if (abfd == 0)
506     {
507       as_perror (_("FATAL: Can't create %s"), out_file_name);
508       exit (EXIT_FAILURE);
509     }
510   bfd_set_format (abfd, bfd_object);
511   bfd_set_arch_mach (abfd, bfd_arch_h8300, 0);
512   subseg_set (1, 0);
513   subseg_set (2, 0);
514   subseg_set (3, 0);
515   for (frchain_ptr = frchain_root;
516        frchain_ptr != (struct frchain *) NULL;
517        frchain_ptr = frchain_ptr->frch_next)
518     {
519       /* Run through all the sub-segments and align them up.  Also
520          close any open frags.  We tack a .fill onto the end of the
521          frag chain so that any .align's size can be worked by looking
522          at the next frag.  */
523
524       subseg_set (frchain_ptr->frch_seg, frchain_ptr->frch_subseg);
525 #ifndef SUB_SEGMENT_ALIGN
526 #define SUB_SEGMENT_ALIGN(SEG) 2
527 #endif
528       frag_align (SUB_SEGMENT_ALIGN (now_seg), 0, 0);
529       frag_wane (frag_now);
530       frag_now->fr_fix = 0;
531       know (frag_now->fr_next == NULL);
532     }
533
534   /* Now build one big frag chain for each segment, linked through
535      fr_next.  */
536   for (i = SEG_E0; i < SEG_UNKNOWN; i++)
537     {
538       fragS **prev_frag_ptr_ptr;
539       struct frchain *next_frchain_ptr;
540
541 #if 0
542       struct frag **head_ptr = segment_info[i].frag_root;
543 #endif
544
545       segment_info[i].frag_root = segment_info[i].frchainP->frch_root;
546 #if 0
547       /* I'm not sure what this is for.  */
548       for (frchain_ptr = segment_info[i].frchainP->frch_root;
549            frchain_ptr != (struct frchain *) NULL;
550            frchain_ptr = frchain_ptr->frch_next)
551         {
552           *head_ptr = frchain_ptr;
553           head_ptr = &frchain_ptr->next;
554         }
555 #endif
556     }
557
558   for (i = SEG_E0; i < SEG_UNKNOWN; i++)
559     relax_segment (segment_info[i].frag_root, i);
560
561   /* Relaxation has completed.  Freeze all syms.  */
562   finalize_syms = 1;
563
564   /* Now the addresses of the frags are correct within the segment.  */
565
566   bfd_as_write_hook ();
567   bfd_close (abfd);
568 }
569
570 #endif
571
572 H_SET_TEXT_SIZE (a, b)
573 {
574   abort ();
575 }
576
577 H_GET_TEXT_SIZE ()
578 {
579   abort ();
580 }
581
582 H_SET_BSS_SIZE ()
583 {
584   abort ();
585 }
586
587 H_SET_STRING_SIZE ()
588 {
589   abort ();
590 }
591
592 H_SET_RELOCATION_SIZE ()
593 {
594   abort ();
595 }
596
597 H_SET_MAGIC_NUMBER ()
598 {
599   abort ();
600 }
601
602 H_GET_FILE_SIZE ()
603 {
604   abort ();
605 }
606
607 H_GET_TEXT_RELOCATION_SIZE ()
608 {
609   abort ();
610 }