* config/obj-aout.c (obj_aout_frob_symbol): Use bfd_ind_section_ptr and
[external/binutils.git] / gas / subsegs.c
1 /* subsegs.c - subsegments -
2    Copyright (C) 1987, 1990, 1991, 1992, 1993, 1994
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
19    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
20
21 /*
22  * Segments & sub-segments.
23  */
24
25 #include "as.h"
26
27 #include "subsegs.h"
28 #include "obstack.h"
29
30 frchainS *frchain_root, *frchain_now;
31
32 #ifndef BFD_ASSEMBLER
33 #ifdef MANY_SEGMENTS
34 segment_info_type segment_info[SEG_MAXIMUM_ORDINAL];
35
36 #else
37 /* Commented in "subsegs.h". */
38 frchainS *data0_frchainP, *bss0_frchainP;
39
40 #endif /* MANY_SEGMENTS */
41 char *const seg_name[] =
42 {
43   "absolute",
44 #ifdef MANY_SEGMENTS
45   "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9",
46 #else
47   "text",
48   "data",
49   "bss",
50 #endif /* MANY_SEGMENTS */
51   "unknown",
52   "ASSEMBLER-INTERNAL-LOGIC-ERROR!",
53   "expr",
54   "debug",
55   "transfert vector preload",
56   "transfert vector postload",
57   "register",
58   "",
59 };                              /* Used by error reporters, dumpers etc. */
60 #else /* BFD_ASSEMBLER */
61
62 /* Gas segment information for bfd_abs_section_ptr and
63    bfd_und_section_ptr.  */
64 static segment_info_type *abs_seg_info;
65 static segment_info_type *und_seg_info;
66
67 #endif /* BFD_ASSEMBLER */
68
69 static void subseg_set_rest PARAMS ((segT, subsegT));
70 \f
71 void
72 subsegs_begin ()
73 {
74   /* Check table(s) seg_name[], seg_N_TYPE[] is in correct order */
75 #if !defined (MANY_SEGMENTS) && !defined (BFD_ASSEMBLER)
76   know (SEG_ABSOLUTE == 0);
77   know (SEG_TEXT == 1);
78   know (SEG_DATA == 2);
79   know (SEG_BSS == 3);
80   know (SEG_UNKNOWN == 4);
81   know (SEG_GOOF == 5);
82   know (SEG_EXPR == 6);
83   know (SEG_DEBUG == 7);
84   know (SEG_NTV == 8);
85   know (SEG_PTV == 9);
86   know (SEG_REGISTER == 10);
87   know (SEG_MAXIMUM_ORDINAL == SEG_REGISTER);
88 #endif
89
90   obstack_begin (&frags, 5000);
91   frchain_root = NULL;
92   frchain_now = NULL;           /* Warn new_subseg() that we are booting. */
93   /* Fake up 1st frag.  It won't be used=> is ok if obstack...
94      pads the end of it for alignment. */
95   frag_now = (fragS *) obstack_alloc (&frags, SIZEOF_STRUCT_FRAG);
96   memset (frag_now, 0, SIZEOF_STRUCT_FRAG);
97
98 #ifndef BFD_ASSEMBLER
99   /* This 1st frag will not be in any frchain.
100      We simply give subseg_new somewhere to scribble. */
101   now_subseg = 42;              /* Lie for 1st call to subseg_new. */
102 #ifdef MANY_SEGMENTS
103   {
104     int i;
105     for (i = SEG_E0; i < SEG_UNKNOWN; i++)
106       {
107         subseg_set (i, 0);
108         segment_info[i].frchainP = frchain_now;
109       }
110   }
111 #else
112   subseg_set (SEG_DATA, 0);     /* .data 0 */
113   data0_frchainP = frchain_now;
114
115   subseg_set (SEG_BSS, 0);
116   bss0_frchainP = frchain_now;
117
118 #endif /* ! MANY_SEGMENTS */
119 #endif /* ! BFD_ASSEMBLER */
120
121 }
122 \f
123 /*
124  *                      subseg_change()
125  *
126  * Change the subsegment we are in, BUT DO NOT MAKE A NEW FRAG for the
127  * subsegment. If we are already in the correct subsegment, change nothing.
128  * This is used eg as a worker for subseg_set [which does make a new frag_now]
129  * and for changing segments after we have read the source. We construct eg
130  * fixSs even after the source file is read, so we do have to keep the
131  * segment context correct.
132  */
133 void
134 subseg_change (seg, subseg)
135      register segT seg;
136      register int subseg;
137 {
138   now_seg = seg;
139   now_subseg = subseg;
140
141 #ifdef BFD_ASSEMBLER
142   {
143     segment_info_type *seginfo;
144     seginfo = (segment_info_type *) bfd_get_section_userdata (stdoutput, seg);
145     if (! seginfo)
146       {
147         seginfo = (segment_info_type *) xmalloc (sizeof (*seginfo));
148         memset ((PTR) seginfo, 0, sizeof (*seginfo));
149         seginfo->fix_root = NULL;
150         seginfo->fix_tail = NULL;
151         seginfo->bfd_section = seg;
152         seginfo->sym = 0;
153         if (seg == bfd_abs_section_ptr)
154           abs_seg_info = seginfo;
155         else if (seg == bfd_und_section_ptr)
156           und_seg_info = seginfo;
157         else
158           bfd_set_section_userdata (stdoutput, seg, (PTR) seginfo);
159       }
160   }
161 #else
162 #ifdef MANY_SEGMENTS
163   seg_fix_rootP = &segment_info[seg].fix_root;
164   seg_fix_tailP = &segment_info[seg].fix_tail;
165 #else
166   if (seg == SEG_DATA)
167     {
168       seg_fix_rootP = &data_fix_root;
169       seg_fix_tailP = &data_fix_tail;
170     }
171   else if (seg == SEG_TEXT)
172     {
173       seg_fix_rootP = &text_fix_root;
174       seg_fix_tailP = &text_fix_tail;
175     }
176   else
177     {
178       know (seg == SEG_BSS);
179       seg_fix_rootP = &bss_fix_root;
180       seg_fix_tailP = &bss_fix_tail;
181     }
182
183 #endif
184 #endif
185 }
186 \f
187 static void
188 subseg_set_rest (seg, subseg)
189      segT seg;
190      subsegT subseg;
191 {
192   long tmp;                     /* JF for obstack alignment hacking */
193   register frchainS *frcP;      /* crawl frchain chain */
194   register frchainS **lastPP;   /* address of last pointer */
195   frchainS *newP;               /* address of new frchain */
196   register fragS *former_last_fragP;
197   register fragS *new_fragP;
198
199   if (frag_now)         /* If not bootstrapping. */
200     {
201       frag_now->fr_fix = (char*) obstack_next_free (&frags) - frag_now->fr_literal;
202       frag_wane (frag_now);     /* Close off any frag in old subseg. */
203     }
204   /*
205    * It would be nice to keep an obstack for each subsegment, if we swap
206    * subsegments a lot. Hence we would have much fewer frag_wanes().
207    */
208   {
209     obstack_finish (&frags);
210     /*
211      * If we don't do the above, the next object we put on obstack frags
212      * will appear to start at the fr_literal of the current frag.
213      * Also, above ensures that the next object will begin on a
214      * address that is aligned correctly for the engine that runs
215      * this program.
216      */
217   }
218   subseg_change (seg, (int) subseg);
219   /*
220    * Attempt to find or make a frchain for that sub seg.
221    * Crawl along chain of frchainSs, begins @ frchain_root.
222    * If we need to make a frchainS, link it into correct
223    * position of chain rooted in frchain_root.
224    */
225   for (frcP = *(lastPP = &frchain_root);
226        frcP && frcP->frch_seg <= seg;
227        frcP = *(lastPP = &frcP->frch_next))
228     {
229       if (frcP->frch_seg == seg
230           && frcP->frch_subseg >= subseg)
231         {
232           break;
233         }
234     }
235   /*
236    * frcP:              Address of the 1st frchainS in correct segment with
237    *            frch_subseg >= subseg.
238    *            We want to either use this frchainS, or we want
239    *            to insert a new frchainS just before it.
240    *
241    *            If frcP==NULL, then we are at the end of the chain
242    *            of frchainS-s. A NULL frcP means we fell off the end
243    *            of the chain looking for a
244    *            frch_subseg >= subseg, so we
245    *            must make a new frchainS.
246    *
247    *            If we ever maintain a pointer to
248    *            the last frchainS in the chain, we change that pointer
249    *            ONLY when frcP==NULL.
250    *
251    * lastPP:    Address of the pointer with value frcP;
252    *            Never NULL.
253    *            May point to frchain_root.
254    *
255    */
256   if (!frcP
257       || (frcP->frch_seg > seg
258           || frcP->frch_subseg > subseg))       /* Kinky logic only works with 2 segments. */
259     {
260       /*
261        * This should be the only code that creates a frchainS.
262        */
263       newP = (frchainS *) obstack_alloc (&frags, sizeof (frchainS));
264       memset (newP, 0, sizeof (frchainS));
265       /* This begines on a good boundary because a obstack_done()
266          preceeded it.  It implies an obstack_done(), so we expect
267          the next object allocated to begin on a correct boundary. */
268       *lastPP = newP;
269       newP->frch_next = frcP;   /* perhaps NULL */
270       (frcP = newP)->frch_subseg = subseg;
271       newP->frch_seg = seg;
272       newP->frch_last = NULL;
273 #ifdef BFD_ASSEMBLER
274       newP->fix_root = NULL;
275       newP->fix_tail = NULL;
276 #endif
277     }
278   /*
279    * Here with frcP ->ing to the frchainS for subseg.
280    */
281   frchain_now = frcP;
282   /*
283    * Make a fresh frag for the subsegment.
284    */
285   /* We expect this to happen on a correct boundary since it was
286      proceeded by a obstack_done(). */
287   tmp = obstack_alignment_mask (&frags);        /* JF disable alignment */
288   obstack_alignment_mask (&frags) = 0;
289   frag_now = (fragS *) obstack_alloc (&frags, SIZEOF_STRUCT_FRAG);
290   memset (frag_now, 0, SIZEOF_STRUCT_FRAG);
291   obstack_alignment_mask (&frags) = tmp;
292   /* But we want any more chars to come immediately after the
293      structure we just made. */
294   new_fragP = frag_now;
295   new_fragP->fr_next = NULL;
296   /*
297    * Append new frag to current frchain.
298    */
299   former_last_fragP = frcP->frch_last;
300   if (former_last_fragP)
301     {
302       know (former_last_fragP->fr_next == NULL);
303       know (frchain_now->frch_root);
304       former_last_fragP->fr_next = new_fragP;
305     }
306   else
307     {
308       frcP->frch_root = new_fragP;
309     }
310   frcP->frch_last = new_fragP;
311 }
312
313 /*
314  *                      subseg_set(segT, subsegT)
315  *
316  * If you attempt to change to the current subsegment, nothing happens.
317  *
318  * In:  segT, subsegT code for new subsegment.
319  *      frag_now -> incomplete frag for current subsegment.
320  *      If frag_now==NULL, then there is no old, incomplete frag, so
321  *      the old frag is not closed off.
322  *
323  * Out: now_subseg, now_seg updated.
324  *      Frchain_now points to the (possibly new) struct frchain for this
325  *      sub-segment.
326  *      Frchain_root updated if needed.
327  */
328
329 #ifndef BFD_ASSEMBLER
330
331 segT
332 subseg_new (segname, subseg)
333      const char *segname;
334      subsegT subseg;
335 {
336   int i;
337
338   for (i = 0; i < (int) SEG_MAXIMUM_ORDINAL; i++)
339     {
340       const char *s;
341
342       s = segment_name ((segT) i);
343       if (strcmp (segname, s) == 0
344           || (segname[0] == '.'
345               && strcmp (segname + 1, s) == 0))
346         {
347           subseg_set ((segT) i, subseg);
348           return (segT) i;
349         }
350 #ifdef obj_segment_name
351       s = obj_segment_name ((segT) i);
352       if (strcmp (segname, s) == 0
353           || (segname[0] == '.'
354               && strcmp (segname + 1, s) == 0))
355         {
356           subseg_set ((segT) i, subseg);
357           return (segT) i;
358         }
359 #endif
360     }
361
362 #ifdef obj_add_segment
363   {
364     segT new_seg;
365     new_seg = obj_add_segment (segname);
366     subseg_set (new_seg, subseg);
367     return new_seg;
368   }
369 #else
370   as_bad ("Attempt to switch to nonexistent segment \"%s\"", segname);
371   return now_seg;
372 #endif
373 }
374
375 void
376 subseg_set (seg, subseg)        /* begin assembly for a new sub-segment */
377      register segT seg;         /* SEG_DATA or SEG_TEXT */
378      register subsegT subseg;
379 {
380 #ifndef MANY_SEGMENTS
381   know (seg == SEG_DATA || seg == SEG_TEXT || seg == SEG_BSS);
382 #endif
383
384   if (seg != now_seg || subseg != now_subseg)
385     {                           /* we just changed sub-segments */
386       subseg_set_rest (seg, subseg);
387     }
388 }
389
390 #else /* BFD_ASSEMBLER */
391
392 segT
393 subseg_get (segname, force_new)
394      const char *segname;
395      int force_new;
396 {
397   segT secptr;
398   segment_info_type *seginfo;
399   const char *now_seg_name = (now_seg
400                               ? bfd_get_section_name (stdoutput, now_seg)
401                               : 0);
402
403   if (!force_new
404       && now_seg_name
405       && (now_seg_name == segname
406           || !strcmp (now_seg_name, segname)))
407     return now_seg;
408
409   if (!force_new)
410     secptr = bfd_make_section_old_way (stdoutput, segname);
411   else
412     secptr = bfd_make_section_anyway (stdoutput, segname);
413
414   seginfo = seg_info (secptr);
415   if (! seginfo)
416     {
417       /* Check whether output_section is set first because secptr may
418          be bfd_abs_section_ptr.  */
419       if (secptr->output_section != secptr)
420         secptr->output_section = secptr;
421       seginfo = (segment_info_type *) xmalloc (sizeof (*seginfo));
422       memset ((PTR) seginfo, 0, sizeof (*seginfo));
423       seginfo->fix_root = NULL;
424       seginfo->fix_tail = NULL;
425       seginfo->bfd_section = secptr;
426       if (secptr == bfd_abs_section_ptr)
427         abs_seg_info = seginfo;
428       else if (secptr == bfd_und_section_ptr)
429         und_seg_info = seginfo;
430       else
431         bfd_set_section_userdata (stdoutput, secptr, (PTR) seginfo);
432       seginfo->frchainP = NULL;
433       seginfo->lineno_list_head = seginfo->lineno_list_tail = NULL;
434       seginfo->sym = NULL;
435       seginfo->dot = NULL;
436     }
437   return secptr;
438 }
439
440 segT
441 subseg_new (segname, subseg)
442      const char *segname;
443      subsegT subseg;
444 {
445   segT secptr;
446   segment_info_type *seginfo;
447
448   secptr = subseg_get (segname, 0);
449   subseg_set_rest (secptr, subseg);
450   seginfo = seg_info (secptr);
451   if (! seginfo->frchainP)
452     seginfo->frchainP = frchain_now;
453   return secptr;
454 }
455
456 /* Like subseg_new, except a new section is always created, even if
457    a section with that name already exists.  */
458 segT
459 subseg_force_new (segname, subseg)
460      const char *segname;
461      subsegT subseg;
462 {
463   segT secptr;
464   segment_info_type *seginfo;
465
466   secptr = subseg_get (segname, 1);
467   subseg_set_rest (secptr, subseg);
468   seginfo = seg_info (secptr);
469   if (! seginfo->frchainP)
470     seginfo->frchainP = frchain_now;
471   return secptr;
472 }
473
474 void
475 subseg_set (secptr, subseg)
476      segT secptr;
477      subsegT subseg;
478 {
479   if (! (secptr == now_seg && subseg == now_subseg))
480     subseg_set_rest (secptr, subseg);
481 }
482
483 #ifndef obj_sec_sym_ok_for_reloc
484 #define obj_sec_sym_ok_for_reloc(SEC)   0
485 #endif
486
487 /* Get the gas information we are storing for a section.  */
488
489 segment_info_type *
490 seg_info (sec)
491      segT sec;
492 {
493   if (sec == bfd_abs_section_ptr)
494     return abs_seg_info;
495   else if (sec == bfd_und_section_ptr)
496     return und_seg_info;
497   else
498     return (segment_info_type *) bfd_get_section_userdata (stdoutput, sec);
499 }
500
501 symbolS *
502 section_symbol (sec)
503      segT sec;
504 {
505   segment_info_type *seginfo = seg_info (sec);
506   symbolS *s;
507
508   if (seginfo == 0)
509     abort ();
510   if (seginfo->sym)
511     return seginfo->sym;
512   s = symbol_find (sec->name);
513   if (!s)
514     {
515 #ifndef EMIT_SECTION_SYMBOLS
516 #define EMIT_SECTION_SYMBOLS 1
517 #endif
518
519       if (EMIT_SECTION_SYMBOLS
520 #ifdef BFD_ASSEMBLER
521           && symbol_table_frozen
522 #endif
523           )
524         s = symbol_new (sec->name, sec, 0, &zero_address_frag);
525       else
526         s = symbol_create (sec->name, sec, 0, &zero_address_frag);
527       S_CLEAR_EXTERNAL (s);
528
529       /* Use the BFD section symbol, if possible.  */
530       if (obj_sec_sym_ok_for_reloc (sec))
531         s->bsym = sec->symbol;
532     }
533   seginfo->sym = s;
534   return s;
535 }
536
537 #endif /* BFD_ASSEMBLER */
538
539 /* end of subsegs.c */