subsegs.c revision 130562
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
30frchainS *frchain_root, *frchain_now;
31
32static struct obstack frchains;
33
34#ifndef BFD_ASSEMBLER
35#ifdef MANY_SEGMENTS
36segment_info_type segment_info[SEG_MAXIMUM_ORDINAL];
37
38#else
39/* Commented in "subsegs.h".  */
40frchainS *data0_frchainP, *bss0_frchainP;
41
42#endif /* MANY_SEGMENTS */
43char 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.  */
68static segment_info_type *abs_seg_info;
69static segment_info_type *und_seg_info;
70
71#endif /* BFD_ASSEMBLER */
72
73static void subseg_set_rest (segT, subsegT);
74
75static fragS dummy_frag;
76
77static frchainS absolute_frchain;
78
79void
80subsegs_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
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 */
148void
149subseg_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
203static void
204subseg_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
334segT
335subseg_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
378void
379subseg_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
399segT
400subseg_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
449segT
450subseg_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.  */
465segT
466subseg_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
479void
480subseg_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
493segment_info_type *
494seg_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
504symbolS *
505section_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
556const 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
569int
570subseg_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
596void
597subsegs_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 */
647