Merge from vendor branch CVS:
[dragonfly.git] / contrib / binutils-2.15 / 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 (segT, subsegT);
74
75 static fragS dummy_frag;
76
77 static frchainS absolute_frchain;
78 \f
79 void
80 subsegs_begin (void)
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 (register segT seg, register int subseg)
150 {
151   now_seg = seg;
152   now_subseg = subseg;
153
154   if (now_seg == absolute_section)
155     return;
156
157 #ifdef BFD_ASSEMBLER
158   {
159     segment_info_type *seginfo;
160     seginfo = (segment_info_type *) bfd_get_section_userdata (stdoutput, seg);
161     if (! seginfo)
162       {
163         seginfo = (segment_info_type *) xmalloc (sizeof (*seginfo));
164         memset ((PTR) seginfo, 0, sizeof (*seginfo));
165         seginfo->fix_root = NULL;
166         seginfo->fix_tail = NULL;
167         seginfo->bfd_section = seg;
168         seginfo->sym = 0;
169         if (seg == bfd_abs_section_ptr)
170           abs_seg_info = seginfo;
171         else if (seg == bfd_und_section_ptr)
172           und_seg_info = seginfo;
173         else
174           bfd_set_section_userdata (stdoutput, seg, (PTR) seginfo);
175       }
176   }
177 #else
178 #ifdef MANY_SEGMENTS
179   seg_fix_rootP = &segment_info[seg].fix_root;
180   seg_fix_tailP = &segment_info[seg].fix_tail;
181 #else
182   if (seg == SEG_DATA)
183     {
184       seg_fix_rootP = &data_fix_root;
185       seg_fix_tailP = &data_fix_tail;
186     }
187   else if (seg == SEG_TEXT)
188     {
189       seg_fix_rootP = &text_fix_root;
190       seg_fix_tailP = &text_fix_tail;
191     }
192   else
193     {
194       know (seg == SEG_BSS);
195       seg_fix_rootP = &bss_fix_root;
196       seg_fix_tailP = &bss_fix_tail;
197     }
198
199 #endif
200 #endif
201 }
202 \f
203 static void
204 subseg_set_rest (segT seg, subsegT subseg)
205 {
206   register frchainS *frcP;      /* crawl frchain chain */
207   register frchainS **lastPP;   /* address of last pointer */
208   frchainS *newP;               /* address of new frchain */
209
210   mri_common_symbol = NULL;
211
212   if (frag_now && frchain_now)
213     frchain_now->frch_frag_now = frag_now;
214
215   assert (frchain_now == 0
216           || now_seg == undefined_section
217           || now_seg == absolute_section
218           || frchain_now->frch_last == frag_now);
219
220   subseg_change (seg, (int) subseg);
221
222   if (seg == absolute_section)
223     {
224       frchain_now = &absolute_frchain;
225       frag_now = &zero_address_frag;
226       return;
227     }
228
229   assert (frchain_now == 0
230           || now_seg == undefined_section
231           || frchain_now->frch_last == frag_now);
232
233   /*
234    * Attempt to find or make a frchain for that sub seg.
235    * Crawl along chain of frchainSs, begins @ frchain_root.
236    * If we need to make a frchainS, link it into correct
237    * position of chain rooted in frchain_root.
238    */
239   for (frcP = *(lastPP = &frchain_root);
240        frcP && frcP->frch_seg <= seg;
241        frcP = *(lastPP = &frcP->frch_next))
242     {
243       if (frcP->frch_seg == seg
244           && frcP->frch_subseg >= subseg)
245         {
246           break;
247         }
248     }
249   /*
250    * frcP:              Address of the 1st frchainS in correct segment with
251    *            frch_subseg >= subseg.
252    *            We want to either use this frchainS, or we want
253    *            to insert a new frchainS just before it.
254    *
255    *            If frcP==NULL, then we are at the end of the chain
256    *            of frchainS-s. A NULL frcP means we fell off the end
257    *            of the chain looking for a
258    *            frch_subseg >= subseg, so we
259    *            must make a new frchainS.
260    *
261    *            If we ever maintain a pointer to
262    *            the last frchainS in the chain, we change that pointer
263    *            ONLY when frcP==NULL.
264    *
265    * lastPP:    Address of the pointer with value frcP;
266    *            Never NULL.
267    *            May point to frchain_root.
268    *
269    */
270   if (!frcP
271       || (frcP->frch_seg > seg
272           || frcP->frch_subseg > subseg))       /* Kinky logic only works with 2 segments.  */
273     {
274       /*
275        * This should be the only code that creates a frchainS.
276        */
277       newP = (frchainS *) obstack_alloc (&frchains, sizeof (frchainS));
278       newP->frch_subseg = subseg;
279       newP->frch_seg = seg;
280 #ifdef BFD_ASSEMBLER
281       newP->fix_root = NULL;
282       newP->fix_tail = NULL;
283 #endif
284       obstack_begin (&newP->frch_obstack, chunksize);
285 #if __GNUC__ >= 2
286       obstack_alignment_mask (&newP->frch_obstack) = __alignof__ (fragS) - 1;
287 #endif
288       newP->frch_frag_now = frag_alloc (&newP->frch_obstack);
289       newP->frch_frag_now->fr_type = rs_fill;
290
291       newP->frch_root = newP->frch_last = newP->frch_frag_now;
292
293       *lastPP = newP;
294       newP->frch_next = frcP;   /* perhaps NULL */
295
296 #ifdef BFD_ASSEMBLER
297       {
298         segment_info_type *seginfo;
299         seginfo = seg_info (seg);
300         if (seginfo && seginfo->frchainP == frcP)
301           seginfo->frchainP = newP;
302       }
303 #endif
304
305       frcP = newP;
306     }
307   /*
308    * Here with frcP pointing to the frchainS for subseg.
309    */
310   frchain_now = frcP;
311   frag_now = frcP->frch_frag_now;
312
313   assert (frchain_now->frch_last == frag_now);
314 }
315
316 /*
317  *                      subseg_set(segT, subsegT)
318  *
319  * If you attempt to change to the current subsegment, nothing happens.
320  *
321  * In:  segT, subsegT code for new subsegment.
322  *      frag_now -> incomplete frag for current subsegment.
323  *      If frag_now==NULL, then there is no old, incomplete frag, so
324  *      the old frag is not closed off.
325  *
326  * Out: now_subseg, now_seg updated.
327  *      Frchain_now points to the (possibly new) struct frchain for this
328  *      sub-segment.
329  *      Frchain_root updated if needed.
330  */
331
332 #ifndef BFD_ASSEMBLER
333
334 segT
335 subseg_new (segname, subseg)
336      const char *segname;
337      subsegT subseg;
338 {
339   int i;
340
341   for (i = 0; i < (int) SEG_MAXIMUM_ORDINAL; i++)
342     {
343       const char *s;
344
345       s = segment_name ((segT) i);
346       if (strcmp (segname, s) == 0
347           || (segname[0] == '.'
348               && strcmp (segname + 1, s) == 0))
349         {
350           subseg_set ((segT) i, subseg);
351           return (segT) i;
352         }
353 #ifdef obj_segment_name
354       s = obj_segment_name ((segT) i);
355       if (strcmp (segname, s) == 0
356           || (segname[0] == '.'
357               && strcmp (segname + 1, s) == 0))
358         {
359           subseg_set ((segT) i, subseg);
360           return (segT) i;
361         }
362 #endif
363     }
364
365 #ifdef obj_add_segment
366   {
367     segT new_seg;
368     new_seg = obj_add_segment (segname);
369     subseg_set (new_seg, subseg);
370     return new_seg;
371   }
372 #else
373   as_bad (_("attempt to switch to nonexistent segment \"%s\""), segname);
374   return now_seg;
375 #endif
376 }
377
378 void
379 subseg_set (seg, subseg)        /* begin assembly for a new sub-segment */
380      register segT seg;         /* SEG_DATA or SEG_TEXT */
381      register subsegT subseg;
382 {
383 #ifndef MANY_SEGMENTS
384   know (seg == SEG_DATA
385         || seg == SEG_TEXT
386         || seg == SEG_BSS
387         || seg == SEG_ABSOLUTE);
388 #endif
389
390   if (seg != now_seg || subseg != now_subseg)
391     {                           /* we just changed sub-segments */
392       subseg_set_rest (seg, subseg);
393     }
394   mri_common_symbol = NULL;
395 }
396
397 #else /* BFD_ASSEMBLER */
398
399 segT
400 subseg_get (const char *segname, int force_new)
401 {
402   segT secptr;
403   segment_info_type *seginfo;
404   const char *now_seg_name = (now_seg
405                               ? bfd_get_section_name (stdoutput, now_seg)
406                               : 0);
407
408   if (!force_new
409       && now_seg_name
410       && (now_seg_name == segname
411           || !strcmp (now_seg_name, segname)))
412     return now_seg;
413
414   if (!force_new)
415     secptr = bfd_make_section_old_way (stdoutput, segname);
416   else
417     secptr = bfd_make_section_anyway (stdoutput, segname);
418
419 #ifdef obj_sec_set_private_data
420   obj_sec_set_private_data (stdoutput, secptr);
421 #endif
422
423   seginfo = seg_info (secptr);
424   if (! seginfo)
425     {
426       /* Check whether output_section is set first because secptr may
427          be bfd_abs_section_ptr.  */
428       if (secptr->output_section != secptr)
429         secptr->output_section = secptr;
430       seginfo = (segment_info_type *) xmalloc (sizeof (*seginfo));
431       memset ((PTR) seginfo, 0, sizeof (*seginfo));
432       seginfo->fix_root = NULL;
433       seginfo->fix_tail = NULL;
434       seginfo->bfd_section = secptr;
435       if (secptr == bfd_abs_section_ptr)
436         abs_seg_info = seginfo;
437       else if (secptr == bfd_und_section_ptr)
438         und_seg_info = seginfo;
439       else
440         bfd_set_section_userdata (stdoutput, secptr, (PTR) seginfo);
441       seginfo->frchainP = NULL;
442       seginfo->lineno_list_head = seginfo->lineno_list_tail = NULL;
443       seginfo->sym = NULL;
444       seginfo->dot = NULL;
445     }
446   return secptr;
447 }
448
449 segT
450 subseg_new (const char *segname, subsegT subseg)
451 {
452   segT secptr;
453   segment_info_type *seginfo;
454
455   secptr = subseg_get (segname, 0);
456   subseg_set_rest (secptr, subseg);
457   seginfo = seg_info (secptr);
458   if (! seginfo->frchainP)
459     seginfo->frchainP = frchain_now;
460   return secptr;
461 }
462
463 /* Like subseg_new, except a new section is always created, even if
464    a section with that name already exists.  */
465 segT
466 subseg_force_new (const char *segname, subsegT subseg)
467 {
468   segT secptr;
469   segment_info_type *seginfo;
470
471   secptr = subseg_get (segname, 1);
472   subseg_set_rest (secptr, subseg);
473   seginfo = seg_info (secptr);
474   if (! seginfo->frchainP)
475     seginfo->frchainP = frchain_now;
476   return secptr;
477 }
478
479 void
480 subseg_set (segT secptr, subsegT subseg)
481 {
482   if (! (secptr == now_seg && subseg == now_subseg))
483     subseg_set_rest (secptr, subseg);
484   mri_common_symbol = NULL;
485 }
486
487 #ifndef obj_sec_sym_ok_for_reloc
488 #define obj_sec_sym_ok_for_reloc(SEC)   0
489 #endif
490
491 /* Get the gas information we are storing for a section.  */
492
493 segment_info_type *
494 seg_info (segT sec)
495 {
496   if (sec == bfd_abs_section_ptr)
497     return abs_seg_info;
498   else if (sec == bfd_und_section_ptr)
499     return und_seg_info;
500   else
501     return (segment_info_type *) bfd_get_section_userdata (stdoutput, sec);
502 }
503
504 symbolS *
505 section_symbol (segT sec)
506 {
507   segment_info_type *seginfo = seg_info (sec);
508   symbolS *s;
509
510   if (seginfo == 0)
511     abort ();
512   if (seginfo->sym)
513     return seginfo->sym;
514
515 #ifndef EMIT_SECTION_SYMBOLS
516 #define EMIT_SECTION_SYMBOLS 1
517 #endif
518
519   if (! EMIT_SECTION_SYMBOLS || symbol_table_frozen)
520     {
521       /* Here we know it won't be going into the symbol table.  */
522       s = symbol_create (sec->symbol->name, sec, 0, &zero_address_frag);
523     }
524   else
525     {
526       s = symbol_find_base (sec->symbol->name, 0);
527       if (s == NULL)
528         s = symbol_new (sec->symbol->name, sec, 0, &zero_address_frag);
529       else
530         {
531           if (S_GET_SEGMENT (s) == undefined_section)
532             {
533               S_SET_SEGMENT (s, sec);
534               symbol_set_frag (s, &zero_address_frag);
535             }
536         }
537     }
538
539   S_CLEAR_EXTERNAL (s);
540
541   /* Use the BFD section symbol, if possible.  */
542   if (obj_sec_sym_ok_for_reloc (sec))
543     symbol_set_bfdsym (s, sec->symbol);
544   else
545     symbol_get_bfdsym (s)->flags |= BSF_SECTION_SYM;
546
547   seginfo->sym = s;
548   return s;
549 }
550
551 #endif /* BFD_ASSEMBLER */
552
553 /* Return whether the specified segment is thought to hold text.  */
554
555 #ifndef BFD_ASSEMBLER
556 const char * const nontext_section_names[] = {
557   ".eh_frame",
558   ".gcc_except_table",
559 #ifdef OBJ_COFF
560 #ifndef COFF_LONG_SECTION_NAMES
561   ".eh_fram",
562   ".gcc_exc",
563 #endif
564 #endif
565   NULL
566 };
567 #endif /* ! BFD_ASSEMBLER */
568
569 int
570 subseg_text_p (segT sec)
571 {
572 #ifdef BFD_ASSEMBLER
573   return (bfd_get_section_flags (stdoutput, sec) & SEC_CODE) != 0;
574 #else /* ! BFD_ASSEMBLER */
575   const char * const *p;
576
577   if (sec == data_section || sec == bss_section || sec == absolute_section)
578     return 0;
579
580   for (p = nontext_section_names; *p != NULL; ++p)
581     {
582       if (strcmp (segment_name (sec), *p) == 0)
583         return 0;
584
585 #ifdef obj_segment_name
586       if (strcmp (obj_segment_name (sec), *p) == 0)
587         return 0;
588 #endif
589     }
590
591   return 1;
592
593 #endif /* ! BFD_ASSEMBLER */
594 }
595
596 void
597 subsegs_print_statistics (FILE *file)
598 {
599   frchainS *frchp;
600   fprintf (file, "frag chains:\n");
601   for (frchp = frchain_root; frchp; frchp = frchp->frch_next)
602     {
603       int count = 0;
604       fragS *fragp;
605
606       /* If frch_subseg is non-zero, it's probably been chained onto
607          the end of a previous subsection.  Don't count it again.  */
608       if (frchp->frch_subseg != 0)
609         continue;
610
611       /* Skip gas-internal sections.  */
612       if (segment_name (frchp->frch_seg)[0] == '*')
613         continue;
614
615       for (fragp = frchp->frch_root; fragp; fragp = fragp->fr_next)
616         {
617 #if 0
618           switch (fragp->fr_type)
619             {
620             case rs_fill:
621               fprintf (file, "f"); break;
622             case rs_align:
623               fprintf (file, "a"); break;
624             case rs_align_code:
625               fprintf (file, "c"); break;
626             case rs_org:
627               fprintf (file, "o"); break;
628             case rs_machine_dependent:
629               fprintf (file, "m"); break;
630             case rs_space:
631               fprintf (file, "s"); break;
632             case 0:
633               fprintf (file, "0"); break;
634             default:
635               fprintf (file, "?"); break;
636             }
637 #endif
638           count++;
639         }
640       fprintf (file, "\n");
641       fprintf (file, "\t%p %-10s\t%10d frags\n", (void *) frchp,
642                segment_name (frchp->frch_seg), count);
643     }
644 }
645
646 /* end of subsegs.c */