1 /* subsegs.c - subsegments -
2 Copyright (C) 1987, 90, 91, 92, 93, 94, 95, 96, 1997
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, 5000);
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 * Here with frcP pointing to the frchainS for subseg.
307 frag_now = frcP->frch_frag_now;
309 assert (frchain_now->frch_last == frag_now);
313 * subseg_set(segT, subsegT)
315 * If you attempt to change to the current subsegment, nothing happens.
317 * In: segT, subsegT code for new subsegment.
318 * frag_now -> incomplete frag for current subsegment.
319 * If frag_now==NULL, then there is no old, incomplete frag, so
320 * the old frag is not closed off.
322 * Out: now_subseg, now_seg updated.
323 * Frchain_now points to the (possibly new) struct frchain for this
325 * Frchain_root updated if needed.
328 #ifndef BFD_ASSEMBLER
331 subseg_new (segname, subseg)
337 for (i = 0; i < (int) SEG_MAXIMUM_ORDINAL; i++)
341 s = segment_name ((segT) i);
342 if (strcmp (segname, s) == 0
343 || (segname[0] == '.'
344 && strcmp (segname + 1, s) == 0))
346 subseg_set ((segT) i, subseg);
349 #ifdef obj_segment_name
350 s = obj_segment_name ((segT) i);
351 if (strcmp (segname, s) == 0
352 || (segname[0] == '.'
353 && strcmp (segname + 1, s) == 0))
355 subseg_set ((segT) i, subseg);
361 #ifdef obj_add_segment
364 new_seg = obj_add_segment (segname);
365 subseg_set (new_seg, subseg);
369 as_bad ("Attempt to switch to nonexistent segment \"%s\"", segname);
375 subseg_set (seg, subseg) /* begin assembly for a new sub-segment */
376 register segT seg; /* SEG_DATA or SEG_TEXT */
377 register subsegT subseg;
379 #ifndef MANY_SEGMENTS
380 know (seg == SEG_DATA
383 || seg == SEG_ABSOLUTE);
386 if (seg != now_seg || subseg != now_subseg)
387 { /* we just changed sub-segments */
388 subseg_set_rest (seg, subseg);
390 mri_common_symbol = NULL;
393 #else /* BFD_ASSEMBLER */
396 subseg_get (segname, force_new)
401 segment_info_type *seginfo;
402 const char *now_seg_name = (now_seg
403 ? bfd_get_section_name (stdoutput, now_seg)
408 && (now_seg_name == segname
409 || !strcmp (now_seg_name, segname)))
413 secptr = bfd_make_section_old_way (stdoutput, segname);
415 secptr = bfd_make_section_anyway (stdoutput, segname);
417 seginfo = seg_info (secptr);
420 /* Check whether output_section is set first because secptr may
421 be bfd_abs_section_ptr. */
422 if (secptr->output_section != secptr)
423 secptr->output_section = secptr;
424 seginfo = (segment_info_type *) xmalloc (sizeof (*seginfo));
425 memset ((PTR) seginfo, 0, sizeof (*seginfo));
426 seginfo->fix_root = NULL;
427 seginfo->fix_tail = NULL;
428 seginfo->bfd_section = secptr;
429 if (secptr == bfd_abs_section_ptr)
430 abs_seg_info = seginfo;
431 else if (secptr == bfd_und_section_ptr)
432 und_seg_info = seginfo;
434 bfd_set_section_userdata (stdoutput, secptr, (PTR) seginfo);
435 seginfo->frchainP = NULL;
436 seginfo->lineno_list_head = seginfo->lineno_list_tail = NULL;
444 subseg_new (segname, subseg)
449 segment_info_type *seginfo;
451 secptr = subseg_get (segname, 0);
452 subseg_set_rest (secptr, subseg);
453 seginfo = seg_info (secptr);
454 if (! seginfo->frchainP)
455 seginfo->frchainP = frchain_now;
459 /* Like subseg_new, except a new section is always created, even if
460 a section with that name already exists. */
462 subseg_force_new (segname, subseg)
467 segment_info_type *seginfo;
469 secptr = subseg_get (segname, 1);
470 subseg_set_rest (secptr, subseg);
471 seginfo = seg_info (secptr);
472 if (! seginfo->frchainP)
473 seginfo->frchainP = frchain_now;
478 subseg_set (secptr, subseg)
482 if (! (secptr == now_seg && subseg == now_subseg))
483 subseg_set_rest (secptr, subseg);
484 mri_common_symbol = NULL;
487 #ifndef obj_sec_sym_ok_for_reloc
488 #define obj_sec_sym_ok_for_reloc(SEC) 0
491 /* Get the gas information we are storing for a section. */
497 if (sec == bfd_abs_section_ptr)
499 else if (sec == bfd_und_section_ptr)
502 return (segment_info_type *) bfd_get_section_userdata (stdoutput, sec);
509 segment_info_type *seginfo = seg_info (sec);
517 #ifndef EMIT_SECTION_SYMBOLS
518 #define EMIT_SECTION_SYMBOLS 1
521 if (! EMIT_SECTION_SYMBOLS
523 || symbol_table_frozen
526 /* Here we know it won't be going into the symbol table. */
527 s = symbol_create (sec->name, sec, 0, &zero_address_frag);
529 s = symbol_new (sec->name, sec, 0, &zero_address_frag);
530 S_CLEAR_EXTERNAL (s);
532 /* Use the BFD section symbol, if possible. */
533 if (obj_sec_sym_ok_for_reloc (sec))
534 s->bsym = sec->symbol;
540 #endif /* BFD_ASSEMBLER */
543 subsegs_print_statistics (file)
547 fprintf (file, "frag chains:\n");
548 for (frchp = frchain_root; frchp; frchp = frchp->frch_next)
553 /* If frch_subseg is non-zero, it's probably been chained onto
554 the end of a previous subsection. Don't count it again. */
555 if (frchp->frch_subseg != 0)
558 /* Skip gas-internal sections. */
559 if (segment_name (frchp->frch_seg)[0] == '*')
562 for (fragp = frchp->frch_root; fragp; fragp = fragp->fr_next)
565 switch (fragp->fr_type)
568 fprintf (file, "f"); break;
570 fprintf (file, "a"); break;
572 fprintf (file, "c"); break;
574 fprintf (file, "o"); break;
575 case rs_machine_dependent:
576 fprintf (file, "m"); break;
578 fprintf (file, "s"); break;
580 fprintf (file, "0"); break;
582 fprintf (file, "?"); break;
587 fprintf (file, "\n");
588 fprintf (file, "\t%p %-10s\t%10d frags\n", frchp,
589 segment_name (frchp->frch_seg), count);
593 /* end of subsegs.c */