Merge from vendor branch GCC:
[dragonfly.git] / contrib / binutils-2.14 / gas / subsegs.c
1 /* subsegs.c - subsegments -
2    Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3    1999, 2000, 2002
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 || symbol_table_frozen)
530     {
531       /* Here we know it won't be going into the symbol table.  */
532       s = symbol_create (sec->symbol->name, sec, 0, &zero_address_frag);
533     }
534   else
535     {
536       s = symbol_find_base (sec->symbol->name, 0);
537       if (s == NULL)
538         s = symbol_new (sec->symbol->name, sec, 0, &zero_address_frag);
539       else
540         {
541           if (S_GET_SEGMENT (s) == undefined_section)
542             {
543               S_SET_SEGMENT (s, sec);
544               symbol_set_frag (s, &zero_address_frag);
545             }
546         }
547     }
548
549   S_CLEAR_EXTERNAL (s);
550
551   /* Use the BFD section symbol, if possible.  */
552   if (obj_sec_sym_ok_for_reloc (sec))
553     symbol_set_bfdsym (s, sec->symbol);
554   else
555     symbol_get_bfdsym (s)->flags |= BSF_SECTION_SYM;
556
557   seginfo->sym = s;
558   return s;
559 }
560
561 #endif /* BFD_ASSEMBLER */
562
563 /* Return whether the specified segment is thought to hold text.  */
564
565 #ifndef BFD_ASSEMBLER
566 const char * const nontext_section_names[] = {
567   ".eh_frame",
568   ".gcc_except_table",
569 #ifdef OBJ_COFF
570 #ifndef COFF_LONG_SECTION_NAMES
571   ".eh_fram",
572   ".gcc_exc",
573 #endif
574 #endif
575   NULL
576 };
577 #endif /* ! BFD_ASSEMBLER */
578
579 int
580 subseg_text_p (sec)
581      segT sec;
582 {
583 #ifdef BFD_ASSEMBLER
584   return (bfd_get_section_flags (stdoutput, sec) & SEC_CODE) != 0;
585 #else /* ! BFD_ASSEMBLER */
586   const char * const *p;
587
588   if (sec == data_section || sec == bss_section || sec == absolute_section)
589     return 0;
590
591   for (p = nontext_section_names; *p != NULL; ++p)
592     {
593       if (strcmp (segment_name (sec), *p) == 0)
594         return 0;
595
596 #ifdef obj_segment_name
597       if (strcmp (obj_segment_name (sec), *p) == 0)
598         return 0;
599 #endif
600     }
601
602   return 1;
603
604 #endif /* ! BFD_ASSEMBLER */
605 }
606
607 void
608 subsegs_print_statistics (file)
609      FILE *file;
610 {
611   frchainS *frchp;
612   fprintf (file, "frag chains:\n");
613   for (frchp = frchain_root; frchp; frchp = frchp->frch_next)
614     {
615       int count = 0;
616       fragS *fragp;
617
618       /* If frch_subseg is non-zero, it's probably been chained onto
619          the end of a previous subsection.  Don't count it again.  */
620       if (frchp->frch_subseg != 0)
621         continue;
622
623       /* Skip gas-internal sections.  */
624       if (segment_name (frchp->frch_seg)[0] == '*')
625         continue;
626
627       for (fragp = frchp->frch_root; fragp; fragp = fragp->fr_next)
628         {
629 #if 0
630           switch (fragp->fr_type)
631             {
632             case rs_fill:
633               fprintf (file, "f"); break;
634             case rs_align:
635               fprintf (file, "a"); break;
636             case rs_align_code:
637               fprintf (file, "c"); break;
638             case rs_org:
639               fprintf (file, "o"); break;
640             case rs_machine_dependent:
641               fprintf (file, "m"); break;
642             case rs_space:
643               fprintf (file, "s"); break;
644             case 0:
645               fprintf (file, "0"); break;
646             default:
647               fprintf (file, "?"); break;
648             }
649 #endif
650           count++;
651         }
652       fprintf (file, "\n");
653       fprintf (file, "\t%p %-10s\t%10d frags\n", (void *) frchp,
654                segment_name (frchp->frch_seg), count);
655     }
656 }
657
658 /* end of subsegs.c */