Initial import from FreeBSD RELENG_4:
[games.git] / contrib / binutils / gas / subsegs.c
1 /* subsegs.c - subsegments -
2    Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3    1999, 2000
4    Free Software Foundation, Inc.
5
6    This file is part of GAS, the GNU Assembler.
7
8    GAS is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2, or (at your option)
11    any later version.
12
13    GAS is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with GAS; see the file COPYING.  If not, write to the Free
20    Software Foundation, 59 Temple Place - Suite 330, Boston, MA
21    02111-1307, USA.  */
22
23 /* Segments & sub-segments.  */
24
25 #include "as.h"
26
27 #include "subsegs.h"
28 #include "obstack.h"
29
30 frchainS *frchain_root, *frchain_now;
31
32 static struct obstack frchains;
33
34 #ifndef BFD_ASSEMBLER
35 #ifdef MANY_SEGMENTS
36 segment_info_type segment_info[SEG_MAXIMUM_ORDINAL];
37
38 #else
39 /* Commented in "subsegs.h".  */
40 frchainS *data0_frchainP, *bss0_frchainP;
41
42 #endif /* MANY_SEGMENTS */
43 char const *const seg_name[] = {
44   "absolute",
45 #ifdef MANY_SEGMENTS
46   "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9",
47   "e10", "e11", "e12", "e13", "e14", "e15", "e16", "e17", "e18", "e19",
48   "e20", "e21", "e22", "e23", "e24", "e25", "e26", "e27", "e28", "e29",
49   "e30", "e31", "e32", "e33", "e34", "e35", "e36", "e37", "e38", "e39",
50 #else
51   "text",
52   "data",
53   "bss",
54 #endif /* MANY_SEGMENTS */
55   "unknown",
56   "ASSEMBLER-INTERNAL-LOGIC-ERROR!",
57   "expr",
58   "debug",
59   "transfert vector preload",
60   "transfert vector postload",
61   "register",
62   "",
63 };                              /* Used by error reporters, dumpers etc.  */
64 #else /* BFD_ASSEMBLER */
65
66 /* Gas segment information for bfd_abs_section_ptr and
67    bfd_und_section_ptr.  */
68 static segment_info_type *abs_seg_info;
69 static segment_info_type *und_seg_info;
70
71 #endif /* BFD_ASSEMBLER */
72
73 static void subseg_set_rest PARAMS ((segT, subsegT));
74
75 static fragS dummy_frag;
76
77 static frchainS absolute_frchain;
78 \f
79 void
80 subsegs_begin ()
81 {
82   /* Check table(s) seg_name[], seg_N_TYPE[] is in correct order */
83 #if !defined (MANY_SEGMENTS) && !defined (BFD_ASSEMBLER)
84   know (SEG_ABSOLUTE == 0);
85   know (SEG_TEXT == 1);
86   know (SEG_DATA == 2);
87   know (SEG_BSS == 3);
88   know (SEG_UNKNOWN == 4);
89   know (SEG_GOOF == 5);
90   know (SEG_EXPR == 6);
91   know (SEG_DEBUG == 7);
92   know (SEG_NTV == 8);
93   know (SEG_PTV == 9);
94   know (SEG_REGISTER == 10);
95   know (SEG_MAXIMUM_ORDINAL == SEG_REGISTER);
96 #endif
97
98   obstack_begin (&frchains, chunksize);
99 #if __GNUC__ >= 2
100   obstack_alignment_mask (&frchains) = __alignof__ (frchainS) - 1;
101 #endif
102
103   frchain_root = NULL;
104   frchain_now = NULL;           /* Warn new_subseg() that we are booting.  */
105
106   frag_now = &dummy_frag;
107
108 #ifndef BFD_ASSEMBLER
109   now_subseg = 42;              /* Lie for 1st call to subseg_new.  */
110 #ifdef MANY_SEGMENTS
111   {
112     int i;
113     for (i = SEG_E0; i < SEG_UNKNOWN; i++)
114       {
115         subseg_set (i, 0);
116         segment_info[i].frchainP = frchain_now;
117       }
118   }
119 #else
120   subseg_set (SEG_DATA, 0);     /* .data 0 */
121   data0_frchainP = frchain_now;
122
123   subseg_set (SEG_BSS, 0);
124   bss0_frchainP = frchain_now;
125
126 #endif /* ! MANY_SEGMENTS */
127 #endif /* ! BFD_ASSEMBLER */
128
129   absolute_frchain.frch_seg = absolute_section;
130   absolute_frchain.frch_subseg = 0;
131 #ifdef BFD_ASSEMBLER
132   absolute_frchain.fix_root = absolute_frchain.fix_tail = 0;
133 #endif
134   absolute_frchain.frch_frag_now = &zero_address_frag;
135   absolute_frchain.frch_root = absolute_frchain.frch_last = &zero_address_frag;
136 }
137 \f
138 /*
139  *                      subseg_change()
140  *
141  * Change the subsegment we are in, BUT DO NOT MAKE A NEW FRAG for the
142  * subsegment. If we are already in the correct subsegment, change nothing.
143  * This is used eg as a worker for subseg_set [which does make a new frag_now]
144  * and for changing segments after we have read the source. We construct eg
145  * fixSs even after the source file is read, so we do have to keep the
146  * segment context correct.
147  */
148 void
149 subseg_change (seg, subseg)
150      register segT seg;
151      register int subseg;
152 {
153   now_seg = seg;
154   now_subseg = subseg;
155
156   if (now_seg == absolute_section)
157     return;
158
159 #ifdef BFD_ASSEMBLER
160   {
161     segment_info_type *seginfo;
162     seginfo = (segment_info_type *) bfd_get_section_userdata (stdoutput, seg);
163     if (! seginfo)
164       {
165         seginfo = (segment_info_type *) xmalloc (sizeof (*seginfo));
166         memset ((PTR) seginfo, 0, sizeof (*seginfo));
167         seginfo->fix_root = NULL;
168         seginfo->fix_tail = NULL;
169         seginfo->bfd_section = seg;
170         seginfo->sym = 0;
171         if (seg == bfd_abs_section_ptr)
172           abs_seg_info = seginfo;
173         else if (seg == bfd_und_section_ptr)
174           und_seg_info = seginfo;
175         else
176           bfd_set_section_userdata (stdoutput, seg, (PTR) seginfo);
177       }
178   }
179 #else
180 #ifdef MANY_SEGMENTS
181   seg_fix_rootP = &segment_info[seg].fix_root;
182   seg_fix_tailP = &segment_info[seg].fix_tail;
183 #else
184   if (seg == SEG_DATA)
185     {
186       seg_fix_rootP = &data_fix_root;
187       seg_fix_tailP = &data_fix_tail;
188     }
189   else if (seg == SEG_TEXT)
190     {
191       seg_fix_rootP = &text_fix_root;
192       seg_fix_tailP = &text_fix_tail;
193     }
194   else
195     {
196       know (seg == SEG_BSS);
197       seg_fix_rootP = &bss_fix_root;
198       seg_fix_tailP = &bss_fix_tail;
199     }
200
201 #endif
202 #endif
203 }
204 \f
205 static void
206 subseg_set_rest (seg, subseg)
207      segT seg;
208      subsegT subseg;
209 {
210   register frchainS *frcP;      /* crawl frchain chain */
211   register frchainS **lastPP;   /* address of last pointer */
212   frchainS *newP;               /* address of new frchain */
213
214   mri_common_symbol = NULL;
215
216   if (frag_now && frchain_now)
217     frchain_now->frch_frag_now = frag_now;
218
219   assert (frchain_now == 0
220           || now_seg == undefined_section
221           || now_seg == absolute_section
222           || frchain_now->frch_last == frag_now);
223
224   subseg_change (seg, (int) subseg);
225
226   if (seg == absolute_section)
227     {
228       frchain_now = &absolute_frchain;
229       frag_now = &zero_address_frag;
230       return;
231     }
232
233   assert (frchain_now == 0
234           || now_seg == undefined_section
235           || frchain_now->frch_last == frag_now);
236
237   /*
238    * Attempt to find or make a frchain for that sub seg.
239    * Crawl along chain of frchainSs, begins @ frchain_root.
240    * If we need to make a frchainS, link it into correct
241    * position of chain rooted in frchain_root.
242    */
243   for (frcP = *(lastPP = &frchain_root);
244        frcP && frcP->frch_seg <= seg;
245        frcP = *(lastPP = &frcP->frch_next))
246     {
247       if (frcP->frch_seg == seg
248           && frcP->frch_subseg >= subseg)
249         {
250           break;
251         }
252     }
253   /*
254    * frcP:              Address of the 1st frchainS in correct segment with
255    *            frch_subseg >= subseg.
256    *            We want to either use this frchainS, or we want
257    *            to insert a new frchainS just before it.
258    *
259    *            If frcP==NULL, then we are at the end of the chain
260    *            of frchainS-s. A NULL frcP means we fell off the end
261    *            of the chain looking for a
262    *            frch_subseg >= subseg, so we
263    *            must make a new frchainS.
264    *
265    *            If we ever maintain a pointer to
266    *            the last frchainS in the chain, we change that pointer
267    *            ONLY when frcP==NULL.
268    *
269    * lastPP:    Address of the pointer with value frcP;
270    *            Never NULL.
271    *            May point to frchain_root.
272    *
273    */
274   if (!frcP
275       || (frcP->frch_seg > seg
276           || frcP->frch_subseg > subseg))       /* Kinky logic only works with 2 segments.  */
277     {
278       /*
279        * This should be the only code that creates a frchainS.
280        */
281       newP = (frchainS *) obstack_alloc (&frchains, sizeof (frchainS));
282       newP->frch_subseg = subseg;
283       newP->frch_seg = seg;
284 #ifdef BFD_ASSEMBLER
285       newP->fix_root = NULL;
286       newP->fix_tail = NULL;
287 #endif
288       obstack_begin (&newP->frch_obstack, chunksize);
289 #if __GNUC__ >= 2
290       obstack_alignment_mask (&newP->frch_obstack) = __alignof__ (fragS) - 1;
291 #endif
292       newP->frch_frag_now = frag_alloc (&newP->frch_obstack);
293       newP->frch_frag_now->fr_type = rs_fill;
294
295       newP->frch_root = newP->frch_last = newP->frch_frag_now;
296
297       *lastPP = newP;
298       newP->frch_next = frcP;   /* perhaps NULL */
299
300 #ifdef BFD_ASSEMBLER
301       {
302         segment_info_type *seginfo;
303         seginfo = seg_info (seg);
304         if (seginfo && seginfo->frchainP == frcP)
305           seginfo->frchainP = newP;
306       }
307 #endif
308
309       frcP = newP;
310     }
311   /*
312    * Here with frcP pointing to the frchainS for subseg.
313    */
314   frchain_now = frcP;
315   frag_now = frcP->frch_frag_now;
316
317   assert (frchain_now->frch_last == frag_now);
318 }
319
320 /*
321  *                      subseg_set(segT, subsegT)
322  *
323  * If you attempt to change to the current subsegment, nothing happens.
324  *
325  * In:  segT, subsegT code for new subsegment.
326  *      frag_now -> incomplete frag for current subsegment.
327  *      If frag_now==NULL, then there is no old, incomplete frag, so
328  *      the old frag is not closed off.
329  *
330  * Out: now_subseg, now_seg updated.
331  *      Frchain_now points to the (possibly new) struct frchain for this
332  *      sub-segment.
333  *      Frchain_root updated if needed.
334  */
335
336 #ifndef BFD_ASSEMBLER
337
338 segT
339 subseg_new (segname, subseg)
340      const char *segname;
341      subsegT subseg;
342 {
343   int i;
344
345   for (i = 0; i < (int) SEG_MAXIMUM_ORDINAL; i++)
346     {
347       const char *s;
348
349       s = segment_name ((segT) i);
350       if (strcmp (segname, s) == 0
351           || (segname[0] == '.'
352               && strcmp (segname + 1, s) == 0))
353         {
354           subseg_set ((segT) i, subseg);
355           return (segT) i;
356         }
357 #ifdef obj_segment_name
358       s = obj_segment_name ((segT) i);
359       if (strcmp (segname, s) == 0
360           || (segname[0] == '.'
361               && strcmp (segname + 1, s) == 0))
362         {
363           subseg_set ((segT) i, subseg);
364           return (segT) i;
365         }
366 #endif
367     }
368
369 #ifdef obj_add_segment
370   {
371     segT new_seg;
372     new_seg = obj_add_segment (segname);
373     subseg_set (new_seg, subseg);
374     return new_seg;
375   }
376 #else
377   as_bad (_("attempt to switch to nonexistent segment \"%s\""), segname);
378   return now_seg;
379 #endif
380 }
381
382 void
383 subseg_set (seg, subseg)        /* begin assembly for a new sub-segment */
384      register segT seg;         /* SEG_DATA or SEG_TEXT */
385      register subsegT subseg;
386 {
387 #ifndef MANY_SEGMENTS
388   know (seg == SEG_DATA
389         || seg == SEG_TEXT
390         || seg == SEG_BSS
391         || seg == SEG_ABSOLUTE);
392 #endif
393
394   if (seg != now_seg || subseg != now_subseg)
395     {                           /* we just changed sub-segments */
396       subseg_set_rest (seg, subseg);
397     }
398   mri_common_symbol = NULL;
399 }
400
401 #else /* BFD_ASSEMBLER */
402
403 segT
404 subseg_get (segname, force_new)
405      const char *segname;
406      int force_new;
407 {
408   segT secptr;
409   segment_info_type *seginfo;
410   const char *now_seg_name = (now_seg
411                               ? bfd_get_section_name (stdoutput, now_seg)
412                               : 0);
413
414   if (!force_new
415       && now_seg_name
416       && (now_seg_name == segname
417           || !strcmp (now_seg_name, segname)))
418     return now_seg;
419
420   if (!force_new)
421     secptr = bfd_make_section_old_way (stdoutput, segname);
422   else
423     secptr = bfd_make_section_anyway (stdoutput, segname);
424
425   seginfo = seg_info (secptr);
426   if (! seginfo)
427     {
428       /* Check whether output_section is set first because secptr may
429          be bfd_abs_section_ptr.  */
430       if (secptr->output_section != secptr)
431         secptr->output_section = secptr;
432       seginfo = (segment_info_type *) xmalloc (sizeof (*seginfo));
433       memset ((PTR) seginfo, 0, sizeof (*seginfo));
434       seginfo->fix_root = NULL;
435       seginfo->fix_tail = NULL;
436       seginfo->bfd_section = secptr;
437       if (secptr == bfd_abs_section_ptr)
438         abs_seg_info = seginfo;
439       else if (secptr == bfd_und_section_ptr)
440         und_seg_info = seginfo;
441       else
442         bfd_set_section_userdata (stdoutput, secptr, (PTR) seginfo);
443       seginfo->frchainP = NULL;
444       seginfo->lineno_list_head = seginfo->lineno_list_tail = NULL;
445       seginfo->sym = NULL;
446       seginfo->dot = NULL;
447     }
448   return secptr;
449 }
450
451 segT
452 subseg_new (segname, subseg)
453      const char *segname;
454      subsegT subseg;
455 {
456   segT secptr;
457   segment_info_type *seginfo;
458
459   secptr = subseg_get (segname, 0);
460   subseg_set_rest (secptr, subseg);
461   seginfo = seg_info (secptr);
462   if (! seginfo->frchainP)
463     seginfo->frchainP = frchain_now;
464   return secptr;
465 }
466
467 /* Like subseg_new, except a new section is always created, even if
468    a section with that name already exists.  */
469 segT
470 subseg_force_new (segname, subseg)
471      const char *segname;
472      subsegT subseg;
473 {
474   segT secptr;
475   segment_info_type *seginfo;
476
477   secptr = subseg_get (segname, 1);
478   subseg_set_rest (secptr, subseg);
479   seginfo = seg_info (secptr);
480   if (! seginfo->frchainP)
481     seginfo->frchainP = frchain_now;
482   return secptr;
483 }
484
485 void
486 subseg_set (secptr, subseg)
487      segT secptr;
488      subsegT subseg;
489 {
490   if (! (secptr == now_seg && subseg == now_subseg))
491     subseg_set_rest (secptr, subseg);
492   mri_common_symbol = NULL;
493 }
494
495 #ifndef obj_sec_sym_ok_for_reloc
496 #define obj_sec_sym_ok_for_reloc(SEC)   0
497 #endif
498
499 /* Get the gas information we are storing for a section.  */
500
501 segment_info_type *
502 seg_info (sec)
503      segT sec;
504 {
505   if (sec == bfd_abs_section_ptr)
506     return abs_seg_info;
507   else if (sec == bfd_und_section_ptr)
508     return und_seg_info;
509   else
510     return (segment_info_type *) bfd_get_section_userdata (stdoutput, sec);
511 }
512
513 symbolS *
514 section_symbol (sec)
515      segT sec;
516 {
517   segment_info_type *seginfo = seg_info (sec);
518   symbolS *s;
519
520   if (seginfo == 0)
521     abort ();
522   if (seginfo->sym)
523     return seginfo->sym;
524
525 #ifndef EMIT_SECTION_SYMBOLS
526 #define EMIT_SECTION_SYMBOLS 1
527 #endif
528
529   if (! EMIT_SECTION_SYMBOLS
530 #ifdef BFD_ASSEMBLER
531       || symbol_table_frozen
532 #endif
533       )
534     {
535       /* Here we know it won't be going into the symbol table.  */
536       s = symbol_create (sec->name, sec, 0, &zero_address_frag);
537     }
538   else
539     {
540       s = symbol_find_base (sec->name, 0);
541       if (s == NULL)
542         s = symbol_new (sec->name, sec, 0, &zero_address_frag);
543       else
544         {
545           if (S_GET_SEGMENT (s) == undefined_section)
546             {
547               S_SET_SEGMENT (s, sec);
548               symbol_set_frag (s, &zero_address_frag);
549             }
550         }
551     }
552
553   S_CLEAR_EXTERNAL (s);
554
555   /* Use the BFD section symbol, if possible.  */
556   if (obj_sec_sym_ok_for_reloc (sec))
557     symbol_set_bfdsym (s, sec->symbol);
558
559   seginfo->sym = s;
560   return s;
561 }
562
563 #endif /* BFD_ASSEMBLER */
564
565 /* Return whether the specified segment is thought to hold text.  */
566
567 #ifndef BFD_ASSEMBLER
568 const char * const nontext_section_names[] = {
569   ".eh_frame",
570   ".gcc_except_table",
571 #ifdef OBJ_COFF
572 #ifndef COFF_LONG_SECTION_NAMES
573   ".eh_fram",
574   ".gcc_exc",
575 #endif
576 #endif
577   NULL
578 };
579 #endif /* ! BFD_ASSEMBLER */
580
581 int
582 subseg_text_p (sec)
583      segT sec;
584 {
585 #ifdef BFD_ASSEMBLER
586   return (bfd_get_section_flags (stdoutput, sec) & SEC_CODE) != 0;
587 #else /* ! BFD_ASSEMBLER */
588   const char * const *p;
589
590   if (sec == data_section || sec == bss_section || sec == absolute_section)
591     return 0;
592
593   for (p = nontext_section_names; *p != NULL; ++p)
594     {
595       if (strcmp (segment_name (sec), *p) == 0)
596         return 0;
597
598 #ifdef obj_segment_name
599       if (strcmp (obj_segment_name (sec), *p) == 0)
600         return 0;
601 #endif
602     }
603
604   return 1;
605
606 #endif /* ! BFD_ASSEMBLER */
607 }
608
609 void
610 subsegs_print_statistics (file)
611      FILE *file;
612 {
613   frchainS *frchp;
614   fprintf (file, "frag chains:\n");
615   for (frchp = frchain_root; frchp; frchp = frchp->frch_next)
616     {
617       int count = 0;
618       fragS *fragp;
619
620       /* If frch_subseg is non-zero, it's probably been chained onto
621          the end of a previous subsection.  Don't count it again.  */
622       if (frchp->frch_subseg != 0)
623         continue;
624
625       /* Skip gas-internal sections.  */
626       if (segment_name (frchp->frch_seg)[0] == '*')
627         continue;
628
629       for (fragp = frchp->frch_root; fragp; fragp = fragp->fr_next)
630         {
631 #if 0
632           switch (fragp->fr_type)
633             {
634             case rs_fill:
635               fprintf (file, "f"); break;
636             case rs_align:
637               fprintf (file, "a"); break;
638             case rs_align_code:
639               fprintf (file, "c"); break;
640             case rs_org:
641               fprintf (file, "o"); break;
642             case rs_machine_dependent:
643               fprintf (file, "m"); break;
644             case rs_space:
645               fprintf (file, "s"); break;
646             case 0:
647               fprintf (file, "0"); break;
648             default:
649               fprintf (file, "?"); break;
650             }
651 #endif
652           count++;
653         }
654       fprintf (file, "\n");
655       fprintf (file, "\t%p %-10s\t%10d frags\n", frchp,
656                segment_name (frchp->frch_seg), count);
657     }
658 }
659
660 /* end of subsegs.c */