1 /* subsegs.c - subsegments -
2 Copyright (C) 1987, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 2000
3 Free Software Foundation, Inc.
5 This file is part of GAS, the GNU Assembler.
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)
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.
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 the Free
19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
23 * Segments & sub-segments.
31 frchainS *frchain_root, *frchain_now;
33 static struct obstack frchains;
37 segment_info_type segment_info[SEG_MAXIMUM_ORDINAL];
40 /* Commented in "subsegs.h". */
41 frchainS *data0_frchainP, *bss0_frchainP;
43 #endif /* MANY_SEGMENTS */
44 char const *const seg_name[] =
48 "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9",
49 "e10", "e11", "e12", "e13", "e14", "e15", "e16", "e17", "e18", "e19",
50 "e20", "e21", "e22", "e23", "e24", "e25", "e26", "e27", "e28", "e29",
51 "e30", "e31", "e32", "e33", "e34", "e35", "e36", "e37", "e38", "e39",
56 #endif /* MANY_SEGMENTS */
58 "ASSEMBLER-INTERNAL-LOGIC-ERROR!",
61 "transfert vector preload",
62 "transfert vector postload",
65 }; /* Used by error reporters, dumpers etc. */
66 #else /* BFD_ASSEMBLER */
68 /* Gas segment information for bfd_abs_section_ptr and
69 bfd_und_section_ptr. */
70 static segment_info_type *abs_seg_info;
71 static segment_info_type *und_seg_info;
73 #endif /* BFD_ASSEMBLER */
75 static void subseg_set_rest PARAMS ((segT, subsegT));
77 static fragS dummy_frag;
79 static frchainS absolute_frchain;
84 /* Check table(s) seg_name[], seg_N_TYPE[] is in correct order */
85 #if !defined (MANY_SEGMENTS) && !defined (BFD_ASSEMBLER)
86 know (SEG_ABSOLUTE == 0);
90 know (SEG_UNKNOWN == 4);
93 know (SEG_DEBUG == 7);
96 know (SEG_REGISTER == 10);
97 know (SEG_MAXIMUM_ORDINAL == SEG_REGISTER);
100 obstack_begin (&frchains, chunksize);
102 obstack_alignment_mask (&frchains) = __alignof__ (frchainS) - 1;
106 frchain_now = NULL; /* Warn new_subseg() that we are booting. */
108 frag_now = &dummy_frag;
110 #ifndef BFD_ASSEMBLER
111 now_subseg = 42; /* Lie for 1st call to subseg_new. */
115 for (i = SEG_E0; i < SEG_UNKNOWN; i++)
118 segment_info[i].frchainP = frchain_now;
122 subseg_set (SEG_DATA, 0); /* .data 0 */
123 data0_frchainP = frchain_now;
125 subseg_set (SEG_BSS, 0);
126 bss0_frchainP = frchain_now;
128 #endif /* ! MANY_SEGMENTS */
129 #endif /* ! BFD_ASSEMBLER */
131 absolute_frchain.frch_seg = absolute_section;
132 absolute_frchain.frch_subseg = 0;
134 absolute_frchain.fix_root = absolute_frchain.fix_tail = 0;
136 absolute_frchain.frch_frag_now = &zero_address_frag;
137 absolute_frchain.frch_root = absolute_frchain.frch_last = &zero_address_frag;
143 * Change the subsegment we are in, BUT DO NOT MAKE A NEW FRAG for the
144 * subsegment. If we are already in the correct subsegment, change nothing.
145 * This is used eg as a worker for subseg_set [which does make a new frag_now]
146 * and for changing segments after we have read the source. We construct eg
147 * fixSs even after the source file is read, so we do have to keep the
148 * segment context correct.
151 subseg_change (seg, subseg)
158 if (now_seg == absolute_section)
163 segment_info_type *seginfo;
164 seginfo = (segment_info_type *) bfd_get_section_userdata (stdoutput, seg);
167 seginfo = (segment_info_type *) xmalloc (sizeof (*seginfo));
168 memset ((PTR) seginfo, 0, sizeof (*seginfo));
169 seginfo->fix_root = NULL;
170 seginfo->fix_tail = NULL;
171 seginfo->bfd_section = seg;
173 if (seg == bfd_abs_section_ptr)
174 abs_seg_info = seginfo;
175 else if (seg == bfd_und_section_ptr)
176 und_seg_info = seginfo;
178 bfd_set_section_userdata (stdoutput, seg, (PTR) seginfo);
183 seg_fix_rootP = &segment_info[seg].fix_root;
184 seg_fix_tailP = &segment_info[seg].fix_tail;
188 seg_fix_rootP = &data_fix_root;
189 seg_fix_tailP = &data_fix_tail;
191 else if (seg == SEG_TEXT)
193 seg_fix_rootP = &text_fix_root;
194 seg_fix_tailP = &text_fix_tail;
198 know (seg == SEG_BSS);
199 seg_fix_rootP = &bss_fix_root;
200 seg_fix_tailP = &bss_fix_tail;
208 subseg_set_rest (seg, subseg)
212 register frchainS *frcP; /* crawl frchain chain */
213 register frchainS **lastPP; /* address of last pointer */
214 frchainS *newP; /* address of new frchain */
216 mri_common_symbol = NULL;
218 if (frag_now && frchain_now)
219 frchain_now->frch_frag_now = frag_now;
221 assert (frchain_now == 0
222 || now_seg == undefined_section
223 || now_seg == absolute_section
224 || frchain_now->frch_last == frag_now);
226 subseg_change (seg, (int) subseg);
228 if (seg == absolute_section)
230 frchain_now = &absolute_frchain;
231 frag_now = &zero_address_frag;
235 assert (frchain_now == 0
236 || now_seg == undefined_section
237 || frchain_now->frch_last == frag_now);
240 * Attempt to find or make a frchain for that sub seg.
241 * Crawl along chain of frchainSs, begins @ frchain_root.
242 * If we need to make a frchainS, link it into correct
243 * position of chain rooted in frchain_root.
245 for (frcP = *(lastPP = &frchain_root);
246 frcP && frcP->frch_seg <= seg;
247 frcP = *(lastPP = &frcP->frch_next))
249 if (frcP->frch_seg == seg
250 && frcP->frch_subseg >= subseg)
256 * frcP: Address of the 1st frchainS in correct segment with
257 * frch_subseg >= subseg.
258 * We want to either use this frchainS, or we want
259 * to insert a new frchainS just before it.
261 * If frcP==NULL, then we are at the end of the chain
262 * of frchainS-s. A NULL frcP means we fell off the end
263 * of the chain looking for a
264 * frch_subseg >= subseg, so we
265 * must make a new frchainS.
267 * If we ever maintain a pointer to
268 * the last frchainS in the chain, we change that pointer
269 * ONLY when frcP==NULL.
271 * lastPP: Address of the pointer with value frcP;
273 * May point to frchain_root.
277 || (frcP->frch_seg > seg
278 || frcP->frch_subseg > subseg)) /* Kinky logic only works with 2 segments. */
281 * This should be the only code that creates a frchainS.
283 newP = (frchainS *) obstack_alloc (&frchains, sizeof (frchainS));
284 newP->frch_subseg = subseg;
285 newP->frch_seg = seg;
287 newP->fix_root = NULL;
288 newP->fix_tail = NULL;
290 obstack_begin (&newP->frch_obstack, chunksize);
292 obstack_alignment_mask (&newP->frch_obstack) = __alignof__ (fragS) - 1;
294 newP->frch_frag_now = frag_alloc (&newP->frch_obstack);
295 newP->frch_frag_now->fr_type = rs_fill;
297 newP->frch_root = newP->frch_last = newP->frch_frag_now;
300 newP->frch_next = frcP; /* perhaps NULL */
304 segment_info_type *seginfo;
305 seginfo = seg_info (seg);
306 if (seginfo && seginfo->frchainP == frcP)
307 seginfo->frchainP = newP;
314 * Here with frcP pointing to the frchainS for subseg.
317 frag_now = frcP->frch_frag_now;
319 assert (frchain_now->frch_last == frag_now);
323 * subseg_set(segT, subsegT)
325 * If you attempt to change to the current subsegment, nothing happens.
327 * In: segT, subsegT code for new subsegment.
328 * frag_now -> incomplete frag for current subsegment.
329 * If frag_now==NULL, then there is no old, incomplete frag, so
330 * the old frag is not closed off.
332 * Out: now_subseg, now_seg updated.
333 * Frchain_now points to the (possibly new) struct frchain for this
335 * Frchain_root updated if needed.
338 #ifndef BFD_ASSEMBLER
341 subseg_new (segname, subseg)
347 for (i = 0; i < (int) SEG_MAXIMUM_ORDINAL; i++)
351 s = segment_name ((segT) i);
352 if (strcmp (segname, s) == 0
353 || (segname[0] == '.'
354 && strcmp (segname + 1, s) == 0))
356 subseg_set ((segT) i, subseg);
359 #ifdef obj_segment_name
360 s = obj_segment_name ((segT) i);
361 if (strcmp (segname, s) == 0
362 || (segname[0] == '.'
363 && strcmp (segname + 1, s) == 0))
365 subseg_set ((segT) i, subseg);
371 #ifdef obj_add_segment
374 new_seg = obj_add_segment (segname);
375 subseg_set (new_seg, subseg);
379 as_bad (_("Attempt to switch to nonexistent segment \"%s\""), segname);
385 subseg_set (seg, subseg) /* begin assembly for a new sub-segment */
386 register segT seg; /* SEG_DATA or SEG_TEXT */
387 register subsegT subseg;
389 #ifndef MANY_SEGMENTS
390 know (seg == SEG_DATA
393 || seg == SEG_ABSOLUTE);
396 if (seg != now_seg || subseg != now_subseg)
397 { /* we just changed sub-segments */
398 subseg_set_rest (seg, subseg);
400 mri_common_symbol = NULL;
403 #else /* BFD_ASSEMBLER */
406 subseg_get (segname, force_new)
411 segment_info_type *seginfo;
412 const char *now_seg_name = (now_seg
413 ? bfd_get_section_name (stdoutput, now_seg)
418 && (now_seg_name == segname
419 || !strcmp (now_seg_name, segname)))
423 secptr = bfd_make_section_old_way (stdoutput, segname);
425 secptr = bfd_make_section_anyway (stdoutput, segname);
427 seginfo = seg_info (secptr);
430 /* Check whether output_section is set first because secptr may
431 be bfd_abs_section_ptr. */
432 if (secptr->output_section != secptr)
433 secptr->output_section = secptr;
434 seginfo = (segment_info_type *) xmalloc (sizeof (*seginfo));
435 memset ((PTR) seginfo, 0, sizeof (*seginfo));
436 seginfo->fix_root = NULL;
437 seginfo->fix_tail = NULL;
438 seginfo->bfd_section = secptr;
439 if (secptr == bfd_abs_section_ptr)
440 abs_seg_info = seginfo;
441 else if (secptr == bfd_und_section_ptr)
442 und_seg_info = seginfo;
444 bfd_set_section_userdata (stdoutput, secptr, (PTR) seginfo);
445 seginfo->frchainP = NULL;
446 seginfo->lineno_list_head = seginfo->lineno_list_tail = NULL;
454 subseg_new (segname, subseg)
459 segment_info_type *seginfo;
461 secptr = subseg_get (segname, 0);
462 subseg_set_rest (secptr, subseg);
463 seginfo = seg_info (secptr);
464 if (! seginfo->frchainP)
465 seginfo->frchainP = frchain_now;
469 /* Like subseg_new, except a new section is always created, even if
470 a section with that name already exists. */
472 subseg_force_new (segname, subseg)
477 segment_info_type *seginfo;
479 secptr = subseg_get (segname, 1);
480 subseg_set_rest (secptr, subseg);
481 seginfo = seg_info (secptr);
482 if (! seginfo->frchainP)
483 seginfo->frchainP = frchain_now;
488 subseg_set (secptr, subseg)
492 if (! (secptr == now_seg && subseg == now_subseg))
493 subseg_set_rest (secptr, subseg);
494 mri_common_symbol = NULL;
497 #ifndef obj_sec_sym_ok_for_reloc
498 #define obj_sec_sym_ok_for_reloc(SEC) 0
501 /* Get the gas information we are storing for a section. */
507 if (sec == bfd_abs_section_ptr)
509 else if (sec == bfd_und_section_ptr)
512 return (segment_info_type *) bfd_get_section_userdata (stdoutput, sec);
519 segment_info_type *seginfo = seg_info (sec);
527 #ifndef EMIT_SECTION_SYMBOLS
528 #define EMIT_SECTION_SYMBOLS 1
531 if (! EMIT_SECTION_SYMBOLS
533 || symbol_table_frozen
537 /* Here we know it won't be going into the symbol table. */
538 s = symbol_create (sec->name, sec, 0, &zero_address_frag);
542 s = symbol_find_base (sec->name, 0);
544 s = symbol_new (sec->name, sec, 0, &zero_address_frag);
547 if (S_GET_SEGMENT (s) == undefined_section)
549 S_SET_SEGMENT (s, sec);
550 symbol_set_frag (s, &zero_address_frag);
555 S_CLEAR_EXTERNAL (s);
557 /* Use the BFD section symbol, if possible. */
558 if (obj_sec_sym_ok_for_reloc (sec))
559 symbol_set_bfdsym (s, sec->symbol);
565 #endif /* BFD_ASSEMBLER */
567 /* Return whether the specified segment is thought to hold text. */
569 #ifndef BFD_ASSEMBLER
570 const char * const nontext_section_names[] =
575 #ifndef COFF_LONG_SECTION_NAMES
582 #endif /* ! BFD_ASSEMBLER */
589 return (bfd_get_section_flags (stdoutput, sec) & SEC_CODE) != 0;
590 #else /* ! BFD_ASSEMBLER */
591 const char * const *p;
593 if (sec == data_section || sec == bss_section)
596 for (p = nontext_section_names; *p != NULL; ++p)
598 if (strcmp (segment_name (sec), *p) == 0)
601 #ifdef obj_segment_name
602 if (strcmp (obj_segment_name (sec), *p) == 0)
609 #endif /* ! BFD_ASSEMBLER */
613 subsegs_print_statistics (file)
617 fprintf (file, "frag chains:\n");
618 for (frchp = frchain_root; frchp; frchp = frchp->frch_next)
623 /* If frch_subseg is non-zero, it's probably been chained onto
624 the end of a previous subsection. Don't count it again. */
625 if (frchp->frch_subseg != 0)
628 /* Skip gas-internal sections. */
629 if (segment_name (frchp->frch_seg)[0] == '*')
632 for (fragp = frchp->frch_root; fragp; fragp = fragp->fr_next)
635 switch (fragp->fr_type)
638 fprintf (file, "f"); break;
640 fprintf (file, "a"); break;
642 fprintf (file, "c"); break;
644 fprintf (file, "o"); break;
645 case rs_machine_dependent:
646 fprintf (file, "m"); break;
648 fprintf (file, "s"); break;
650 fprintf (file, "0"); break;
652 fprintf (file, "?"); break;
657 fprintf (file, "\n");
658 fprintf (file, "\t%p %-10s\t%10d frags\n", frchp,
659 segment_name (frchp->frch_seg), count);
663 /* end of subsegs.c */