bfd/
[deliverable/binutils-gdb.git] / 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 #ifdef obj_sec_set_private_data
426 obj_sec_set_private_data (stdoutput, secptr);
427 #endif
428
429 seginfo = seg_info (secptr);
430 if (! seginfo)
431 {
432 /* Check whether output_section is set first because secptr may
433 be bfd_abs_section_ptr. */
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
455 segT
456 subseg_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. */
473 segT
474 subseg_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
489 void
490 subseg_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
505 segment_info_type *
506 seg_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
517 symbolS *
518 section_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
533 if (! EMIT_SECTION_SYMBOLS || symbol_table_frozen)
534 {
535 /* Here we know it won't be going into the symbol table. */
536 s = symbol_create (sec->symbol->name, sec, 0, &zero_address_frag);
537 }
538 else
539 {
540 s = symbol_find_base (sec->symbol->name, 0);
541 if (s == NULL)
542 s = symbol_new (sec->symbol->name, sec, 0, &zero_address_frag);
543 else
544 {
545 if (S_GET_SEGMENT (s) == undefined_section)
546 {
547 S_SET_SEGMENT (s, sec);
548 symbol_set_frag (s, &zero_address_frag);
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))
557 symbol_set_bfdsym (s, sec->symbol);
558 else
559 symbol_get_bfdsym (s)->flags |= BSF_SECTION_SYM;
560
561 seginfo->sym = s;
562 return s;
563 }
564
565 #endif /* BFD_ASSEMBLER */
566
567 /* Return whether the specified segment is thought to hold text. */
568
569 #ifndef BFD_ASSEMBLER
570 const char * const nontext_section_names[] = {
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
583 int
584 subseg_text_p (sec)
585 segT sec;
586 {
587 #ifdef BFD_ASSEMBLER
588 return (bfd_get_section_flags (stdoutput, sec) & SEC_CODE) != 0;
589 #else /* ! BFD_ASSEMBLER */
590 const char * const *p;
591
592 if (sec == data_section || sec == bss_section || sec == absolute_section)
593 return 0;
594
595 for (p = nontext_section_names; *p != NULL; ++p)
596 {
597 if (strcmp (segment_name (sec), *p) == 0)
598 return 0;
599
600 #ifdef obj_segment_name
601 if (strcmp (obj_segment_name (sec), *p) == 0)
602 return 0;
603 #endif
604 }
605
606 return 1;
607
608 #endif /* ! BFD_ASSEMBLER */
609 }
610
611 void
612 subsegs_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");
657 fprintf (file, "\t%p %-10s\t%10d frags\n", (void *) frchp,
658 segment_name (frchp->frch_seg), count);
659 }
660 }
661
662 /* end of subsegs.c */
This page took 0.070702 seconds and 5 git commands to generate.