* emultempl/beos.em: Remove ARGSUSED.
[deliverable/binutils-gdb.git] / gas / subsegs.c
CommitLineData
252b5132 1/* subsegs.c - subsegments -
f7e42eb4 2 Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
a161fe53 3 1999, 2000, 2002
252b5132
RH
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
ef99799a 23/* Segments & sub-segments. */
252b5132
RH
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
f0e652b4 39/* Commented in "subsegs.h". */
252b5132
RH
40frchainS *data0_frchainP, *bss0_frchainP;
41
42#endif /* MANY_SEGMENTS */
ef99799a 43char const *const seg_name[] = {
252b5132
RH
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 "",
f0e652b4 63}; /* Used by error reporters, dumpers etc. */
252b5132
RH
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 PARAMS ((segT, subsegT));
74
75static fragS dummy_frag;
76
77static frchainS absolute_frchain;
78\f
79void
80subsegs_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;
f0e652b4 104 frchain_now = NULL; /* Warn new_subseg() that we are booting. */
252b5132
RH
105
106 frag_now = &dummy_frag;
107
108#ifndef BFD_ASSEMBLER
f0e652b4 109 now_subseg = 42; /* Lie for 1st call to subseg_new. */
252b5132
RH
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 */
148void
149subseg_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
205static void
206subseg_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
f0e652b4 276 || frcP->frch_subseg > subseg)) /* Kinky logic only works with 2 segments. */
252b5132
RH
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
f0e652b4 308
252b5132
RH
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
338segT
339subseg_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
0e389e77 377 as_bad (_("attempt to switch to nonexistent segment \"%s\""), segname);
252b5132
RH
378 return now_seg;
379#endif
380}
381
382void
383subseg_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
403segT
404subseg_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
2f89ff8d
L
425#ifdef obj_sec_set_private_data
426 obj_sec_set_private_data (stdoutput, secptr);
427#endif
428
252b5132
RH
429 seginfo = seg_info (secptr);
430 if (! seginfo)
431 {
432 /* Check whether output_section is set first because secptr may
546c73f9 433 be bfd_abs_section_ptr. */
252b5132
RH
434 if (secptr->output_section != secptr)
435 secptr->output_section = secptr;
436 seginfo = (segment_info_type *) xmalloc (sizeof (*seginfo));
437 memset ((PTR) seginfo, 0, sizeof (*seginfo));
438 seginfo->fix_root = NULL;
439 seginfo->fix_tail = NULL;
440 seginfo->bfd_section = secptr;
441 if (secptr == bfd_abs_section_ptr)
442 abs_seg_info = seginfo;
443 else if (secptr == bfd_und_section_ptr)
444 und_seg_info = seginfo;
445 else
446 bfd_set_section_userdata (stdoutput, secptr, (PTR) seginfo);
447 seginfo->frchainP = NULL;
448 seginfo->lineno_list_head = seginfo->lineno_list_tail = NULL;
449 seginfo->sym = NULL;
450 seginfo->dot = NULL;
451 }
452 return secptr;
453}
454
455segT
456subseg_new (segname, subseg)
457 const char *segname;
458 subsegT subseg;
459{
460 segT secptr;
461 segment_info_type *seginfo;
462
463 secptr = subseg_get (segname, 0);
464 subseg_set_rest (secptr, subseg);
465 seginfo = seg_info (secptr);
466 if (! seginfo->frchainP)
467 seginfo->frchainP = frchain_now;
468 return secptr;
469}
470
471/* Like subseg_new, except a new section is always created, even if
472 a section with that name already exists. */
473segT
474subseg_force_new (segname, subseg)
475 const char *segname;
476 subsegT subseg;
477{
478 segT secptr;
479 segment_info_type *seginfo;
480
481 secptr = subseg_get (segname, 1);
482 subseg_set_rest (secptr, subseg);
483 seginfo = seg_info (secptr);
484 if (! seginfo->frchainP)
485 seginfo->frchainP = frchain_now;
486 return secptr;
487}
488
489void
490subseg_set (secptr, subseg)
491 segT secptr;
492 subsegT subseg;
493{
494 if (! (secptr == now_seg && subseg == now_subseg))
495 subseg_set_rest (secptr, subseg);
496 mri_common_symbol = NULL;
497}
498
499#ifndef obj_sec_sym_ok_for_reloc
500#define obj_sec_sym_ok_for_reloc(SEC) 0
501#endif
502
503/* Get the gas information we are storing for a section. */
504
505segment_info_type *
506seg_info (sec)
507 segT sec;
508{
509 if (sec == bfd_abs_section_ptr)
510 return abs_seg_info;
511 else if (sec == bfd_und_section_ptr)
512 return und_seg_info;
513 else
514 return (segment_info_type *) bfd_get_section_userdata (stdoutput, sec);
515}
516
517symbolS *
518section_symbol (sec)
519 segT sec;
520{
521 segment_info_type *seginfo = seg_info (sec);
522 symbolS *s;
523
524 if (seginfo == 0)
525 abort ();
526 if (seginfo->sym)
527 return seginfo->sym;
528
529#ifndef EMIT_SECTION_SYMBOLS
530#define EMIT_SECTION_SYMBOLS 1
531#endif
532
a161fe53 533 if (! EMIT_SECTION_SYMBOLS || symbol_table_frozen)
252b5132
RH
534 {
535 /* Here we know it won't be going into the symbol table. */
546c73f9 536 s = symbol_create (sec->symbol->name, sec, 0, &zero_address_frag);
252b5132
RH
537 }
538 else
539 {
546c73f9 540 s = symbol_find_base (sec->symbol->name, 0);
252b5132 541 if (s == NULL)
546c73f9 542 s = symbol_new (sec->symbol->name, sec, 0, &zero_address_frag);
252b5132
RH
543 else
544 {
545 if (S_GET_SEGMENT (s) == undefined_section)
546 {
547 S_SET_SEGMENT (s, sec);
49309057 548 symbol_set_frag (s, &zero_address_frag);
252b5132
RH
549 }
550 }
551 }
552
553 S_CLEAR_EXTERNAL (s);
554
555 /* Use the BFD section symbol, if possible. */
556 if (obj_sec_sym_ok_for_reloc (sec))
49309057 557 symbol_set_bfdsym (s, sec->symbol);
a161fe53
AM
558 else
559 symbol_get_bfdsym (s)->flags |= BSF_SECTION_SYM;
252b5132
RH
560
561 seginfo->sym = s;
562 return s;
563}
564
565#endif /* BFD_ASSEMBLER */
566
b9e57a38
ILT
567/* Return whether the specified segment is thought to hold text. */
568
be2acf27 569#ifndef BFD_ASSEMBLER
ef99799a 570const char * const nontext_section_names[] = {
be2acf27
ILT
571 ".eh_frame",
572 ".gcc_except_table",
573#ifdef OBJ_COFF
574#ifndef COFF_LONG_SECTION_NAMES
575 ".eh_fram",
576 ".gcc_exc",
577#endif
578#endif
579 NULL
580};
581#endif /* ! BFD_ASSEMBLER */
582
b9e57a38
ILT
583int
584subseg_text_p (sec)
585 segT sec;
586{
587#ifdef BFD_ASSEMBLER
588 return (bfd_get_section_flags (stdoutput, sec) & SEC_CODE) != 0;
be2acf27
ILT
589#else /* ! BFD_ASSEMBLER */
590 const char * const *p;
591
ebeb9253 592 if (sec == data_section || sec == bss_section || sec == absolute_section)
264d6861 593 return 0;
be2acf27
ILT
594
595 for (p = nontext_section_names; *p != NULL; ++p)
596 {
597 if (strcmp (segment_name (sec), *p) == 0)
264d6861 598 return 0;
be2acf27
ILT
599
600#ifdef obj_segment_name
601 if (strcmp (obj_segment_name (sec), *p) == 0)
264d6861 602 return 0;
b9e57a38 603#endif
be2acf27
ILT
604 }
605
264d6861 606 return 1;
be2acf27
ILT
607
608#endif /* ! BFD_ASSEMBLER */
b9e57a38
ILT
609}
610
252b5132
RH
611void
612subsegs_print_statistics (file)
613 FILE *file;
614{
615 frchainS *frchp;
616 fprintf (file, "frag chains:\n");
617 for (frchp = frchain_root; frchp; frchp = frchp->frch_next)
618 {
619 int count = 0;
620 fragS *fragp;
621
622 /* If frch_subseg is non-zero, it's probably been chained onto
623 the end of a previous subsection. Don't count it again. */
624 if (frchp->frch_subseg != 0)
625 continue;
626
627 /* Skip gas-internal sections. */
628 if (segment_name (frchp->frch_seg)[0] == '*')
629 continue;
630
631 for (fragp = frchp->frch_root; fragp; fragp = fragp->fr_next)
632 {
633#if 0
634 switch (fragp->fr_type)
635 {
636 case rs_fill:
637 fprintf (file, "f"); break;
638 case rs_align:
639 fprintf (file, "a"); break;
640 case rs_align_code:
641 fprintf (file, "c"); break;
642 case rs_org:
643 fprintf (file, "o"); break;
644 case rs_machine_dependent:
645 fprintf (file, "m"); break;
646 case rs_space:
647 fprintf (file, "s"); break;
648 case 0:
649 fprintf (file, "0"); break;
650 default:
651 fprintf (file, "?"); break;
652 }
653#endif
654 count++;
655 }
656 fprintf (file, "\n");
03e83a45 657 fprintf (file, "\t%p %-10s\t%10d frags\n", (void *) frchp,
252b5132
RH
658 segment_name (frchp->frch_seg), count);
659 }
660}
661
662/* end of subsegs.c */
This page took 0.215495 seconds and 4 git commands to generate.