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