* bfd-in2.h: Rebuilt.
[deliverable/binutils-gdb.git] / gas / subsegs.c
CommitLineData
fecd2382 1/* subsegs.c - subsegments -
cc886e3d
SS
2 Copyright (C) 1987, 1990, 1991, 1992, 1993, 1994
3 Free Software Foundation, Inc.
604633ae 4
a39116f1 5 This file is part of GAS, the GNU Assembler.
604633ae 6
a39116f1
RP
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)
10 any later version.
604633ae 11
a39116f1
RP
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.
604633ae 16
a39116f1
RP
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
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
fecd2382
RP
20
21/*
22 * Segments & sub-segments.
23 */
24
25#include "as.h"
26
27#include "subsegs.h"
28#include "obstack.h"
29
604633ae
ILT
30frchainS *frchain_root, *frchain_now;
31
32#ifndef BFD_ASSEMBLER
a39116f1
RP
33#ifdef MANY_SEGMENTS
34segment_info_type segment_info[SEG_MAXIMUM_ORDINAL];
35
a39116f1 36#else
604633ae
ILT
37/* Commented in "subsegs.h". */
38frchainS *data0_frchainP, *bss0_frchainP;
fecd2382 39
604633ae
ILT
40#endif /* MANY_SEGMENTS */
41char *const seg_name[] =
42{
43 "absolute",
a39116f1 44#ifdef MANY_SEGMENTS
604633ae 45 "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9",
a39116f1 46#else
604633ae
ILT
47 "text",
48 "data",
49 "bss",
50#endif /* MANY_SEGMENTS */
51 "unknown",
52 "ASSEMBLER-INTERNAL-LOGIC-ERROR!",
53 "expr",
54 "debug",
55 "transfert vector preload",
56 "transfert vector postload",
57 "register",
58 "",
59}; /* Used by error reporters, dumpers etc. */
60#endif /* BFD_ASSEMBLER */
fecd2382 61
604633ae 62static void subseg_set_rest PARAMS ((segT, subsegT));
fecd2382
RP
63\f
64void
604633ae 65subsegs_begin ()
fecd2382 66{
604633ae
ILT
67 /* Check table(s) seg_name[], seg_N_TYPE[] is in correct order */
68#if !defined (MANY_SEGMENTS) && !defined (BFD_ASSEMBLER)
69 know (SEG_ABSOLUTE == 0);
70 know (SEG_TEXT == 1);
71 know (SEG_DATA == 2);
72 know (SEG_BSS == 3);
73 know (SEG_UNKNOWN == 4);
74 know (SEG_GOOF == 5);
75 know (SEG_EXPR == 6);
76 know (SEG_DEBUG == 7);
77 know (SEG_NTV == 8);
78 know (SEG_PTV == 9);
79 know (SEG_REGISTER == 10);
80 know (SEG_MAXIMUM_ORDINAL == SEG_REGISTER);
a39116f1 81#endif
604633ae
ILT
82
83 obstack_begin (&frags, 5000);
84 frchain_root = NULL;
85 frchain_now = NULL; /* Warn new_subseg() that we are booting. */
86 /* Fake up 1st frag. It won't be used=> is ok if obstack...
87 pads the end of it for alignment. */
88 frag_now = (fragS *) obstack_alloc (&frags, SIZEOF_STRUCT_FRAG);
cc886e3d 89 memset (frag_now, 0, SIZEOF_STRUCT_FRAG);
604633ae
ILT
90
91#ifndef BFD_ASSEMBLER
92 /* This 1st frag will not be in any frchain.
93 We simply give subseg_new somewhere to scribble. */
94 now_subseg = 42; /* Lie for 1st call to subseg_new. */
a39116f1 95#ifdef MANY_SEGMENTS
604633ae
ILT
96 {
97 int i;
98 for (i = SEG_E0; i < SEG_UNKNOWN; i++)
99 {
100 subseg_set (i, 0);
101 segment_info[i].frchainP = frchain_now;
102 }
103 }
a39116f1 104#else
604633ae
ILT
105 subseg_set (SEG_DATA, 0); /* .data 0 */
106 data0_frchainP = frchain_now;
65bfcf2e 107
604633ae
ILT
108 subseg_set (SEG_BSS, 0);
109 bss0_frchainP = frchain_now;
110
111#endif /* ! MANY_SEGMENTS */
112#endif /* ! BFD_ASSEMBLER */
65bfcf2e 113
fecd2382
RP
114}
115\f
116/*
117 * subseg_change()
118 *
119 * Change the subsegment we are in, BUT DO NOT MAKE A NEW FRAG for the
120 * subsegment. If we are already in the correct subsegment, change nothing.
604633ae 121 * This is used eg as a worker for subseg_set [which does make a new frag_now]
fecd2382
RP
122 * and for changing segments after we have read the source. We construct eg
123 * fixSs even after the source file is read, so we do have to keep the
124 * segment context correct.
125 */
126void
604633ae
ILT
127subseg_change (seg, subseg)
128 register segT seg;
129 register int subseg;
fecd2382 130{
604633ae
ILT
131 now_seg = seg;
132 now_subseg = subseg;
133
134#ifdef BFD_ASSEMBLER
135 {
136 segment_info_type *seginfo;
137 seginfo = (segment_info_type *) bfd_get_section_userdata (stdoutput, seg);
138 if (! seginfo)
139 {
140 seginfo = (segment_info_type *) xmalloc (sizeof (*seginfo));
141 if (! seginfo)
142 abort ();
143 seginfo->fix_root = 0;
604633ae
ILT
144 seginfo->bfd_section = seg;
145 seginfo->sym = 0;
146 bfd_set_section_userdata (stdoutput, seg, (char *) seginfo);
147 }
148 }
149#else
a39116f1 150#ifdef MANY_SEGMENTS
604633ae
ILT
151 seg_fix_rootP = &segment_info[seg].fix_root;
152 seg_fix_tailP = &segment_info[seg].fix_tail;
a39116f1 153#else
604633ae
ILT
154 if (seg == SEG_DATA)
155 {
156 seg_fix_rootP = &data_fix_root;
157 seg_fix_tailP = &data_fix_tail;
158 }
159 else if (seg == SEG_TEXT)
160 {
161 seg_fix_rootP = &text_fix_root;
162 seg_fix_tailP = &text_fix_tail;
163 }
164 else
165 {
166 know (seg == SEG_BSS);
167 seg_fix_rootP = &bss_fix_root;
168 seg_fix_tailP = &bss_fix_tail;
169 }
170
171#endif
a39116f1 172#endif
fecd2382
RP
173}
174\f
604633ae
ILT
175static void
176subseg_set_rest (seg, subseg)
177 segT seg;
178 subsegT subseg;
179{
180 long tmp; /* JF for obstack alignment hacking */
181 register frchainS *frcP; /* crawl frchain chain */
182 register frchainS **lastPP; /* address of last pointer */
183 frchainS *newP; /* address of new frchain */
184 register fragS *former_last_fragP;
185 register fragS *new_fragP;
186
187 if (frag_now) /* If not bootstrapping. */
188 {
189 frag_now->fr_fix = (char*) obstack_next_free (&frags) - frag_now->fr_literal;
190 frag_wane (frag_now); /* Close off any frag in old subseg. */
191 }
192 /*
193 * It would be nice to keep an obstack for each subsegment, if we swap
194 * subsegments a lot. Hence we would have much fewer frag_wanes().
195 */
196 {
197 obstack_finish (&frags);
198 /*
199 * If we don't do the above, the next object we put on obstack frags
200 * will appear to start at the fr_literal of the current frag.
201 * Also, above ensures that the next object will begin on a
202 * address that is aligned correctly for the engine that runs
203 * this program.
204 */
205 }
206 subseg_change (seg, (int) subseg);
207 /*
208 * Attempt to find or make a frchain for that sub seg.
209 * Crawl along chain of frchainSs, begins @ frchain_root.
210 * If we need to make a frchainS, link it into correct
211 * position of chain rooted in frchain_root.
212 */
213 for (frcP = *(lastPP = &frchain_root);
214 frcP && (int) (frcP->frch_seg) <= (int) seg;
215 frcP = *(lastPP = &frcP->frch_next))
216 {
217 if ((int) (frcP->frch_seg) == (int) seg
218 && frcP->frch_subseg >= subseg)
219 {
220 break;
221 }
222 }
223 /*
224 * frcP: Address of the 1st frchainS in correct segment with
225 * frch_subseg >= subseg.
226 * We want to either use this frchainS, or we want
227 * to insert a new frchainS just before it.
228 *
229 * If frcP==NULL, then we are at the end of the chain
230 * of frchainS-s. A NULL frcP means we fell off the end
231 * of the chain looking for a
232 * frch_subseg >= subseg, so we
233 * must make a new frchainS.
234 *
235 * If we ever maintain a pointer to
236 * the last frchainS in the chain, we change that pointer
237 * ONLY when frcP==NULL.
238 *
239 * lastPP: Address of the pointer with value frcP;
240 * Never NULL.
241 * May point to frchain_root.
242 *
243 */
244 if (!frcP
245 || ((int) (frcP->frch_seg) > (int) seg
246 || frcP->frch_subseg > subseg)) /* Kinky logic only works with 2 segments. */
247 {
248 /*
249 * This should be the only code that creates a frchainS.
250 */
251 newP = (frchainS *) obstack_alloc (&frags, sizeof (frchainS));
cc886e3d 252 memset (newP, 0, sizeof (frchainS));
604633ae
ILT
253 /* This begines on a good boundary because a obstack_done()
254 preceeded it. It implies an obstack_done(), so we expect
255 the next object allocated to begin on a correct boundary. */
256 *lastPP = newP;
257 newP->frch_next = frcP; /* perhaps NULL */
258 (frcP = newP)->frch_subseg = subseg;
259 newP->frch_seg = seg;
260 newP->frch_last = NULL;
cc886e3d
SS
261#ifdef BFD_ASSEMBLER
262 newP->fix_root = NULL;
263 newP->fix_tail = NULL;
264#endif
604633ae
ILT
265 }
266 /*
267 * Here with frcP ->ing to the frchainS for subseg.
268 */
269 frchain_now = frcP;
270 /*
271 * Make a fresh frag for the subsegment.
272 */
273 /* We expect this to happen on a correct boundary since it was
274 proceeded by a obstack_done(). */
275 tmp = obstack_alignment_mask (&frags); /* JF disable alignment */
276 obstack_alignment_mask (&frags) = 0;
277 frag_now = (fragS *) obstack_alloc (&frags, SIZEOF_STRUCT_FRAG);
278 memset (frag_now, 0, SIZEOF_STRUCT_FRAG);
279 obstack_alignment_mask (&frags) = tmp;
280 /* But we want any more chars to come immediately after the
281 structure we just made. */
282 new_fragP = frag_now;
283 new_fragP->fr_next = NULL;
284 /*
285 * Append new frag to current frchain.
286 */
287 former_last_fragP = frcP->frch_last;
288 if (former_last_fragP)
289 {
290 know (former_last_fragP->fr_next == NULL);
291 know (frchain_now->frch_root);
292 former_last_fragP->fr_next = new_fragP;
293 }
294 else
295 {
296 frcP->frch_root = new_fragP;
297 }
298 frcP->frch_last = new_fragP;
299}
300
fecd2382 301/*
604633ae 302 * subseg_set(segT, subsegT)
fecd2382
RP
303 *
304 * If you attempt to change to the current subsegment, nothing happens.
305 *
306 * In: segT, subsegT code for new subsegment.
307 * frag_now -> incomplete frag for current subsegment.
308 * If frag_now==NULL, then there is no old, incomplete frag, so
309 * the old frag is not closed off.
310 *
311 * Out: now_subseg, now_seg updated.
312 * Frchain_now points to the (possibly new) struct frchain for this
313 * sub-segment.
314 * Frchain_root updated if needed.
315 */
316
604633ae
ILT
317#ifndef BFD_ASSEMBLER
318
319segT
320subseg_new (segname, subseg)
321 const char *segname;
322 subsegT subseg;
fecd2382 323{
604633ae
ILT
324 int i;
325
326 for (i = 0; i < (int) SEG_MAXIMUM_ORDINAL; i++)
327 {
328 const char *s;
329
330 s = segment_name ((segT) i);
331 if (strcmp (segname, s) == 0
332 || (segname[0] == '.'
333 && strcmp (segname + 1, s) == 0))
f8701a3f 334 {
604633ae
ILT
335 subseg_set ((segT) i, subseg);
336 return (segT) i;
337 }
338#ifdef obj_segment_name
339 s = obj_segment_name ((segT) i);
340 if (strcmp (segname, s) == 0
341 || (segname[0] == '.'
342 && strcmp (segname + 1, s) == 0))
343 {
344 subseg_set ((segT) i, subseg);
345 return (segT) i;
f8701a3f 346 }
a39116f1 347#endif
604633ae 348 }
fecd2382 349
604633ae
ILT
350#ifdef obj_add_segment
351 {
352 segT new_seg;
353 new_seg = obj_add_segment (segname);
354 subseg_set (new_seg, subseg);
355 return new_seg;
356 }
357#else
358 as_bad ("Attempt to switch to nonexistent segment \"%s\"", segname);
359 return now_seg;
360#endif
361}
362
363void
364subseg_set (seg, subseg) /* begin assembly for a new sub-segment */
365 register segT seg; /* SEG_DATA or SEG_TEXT */
366 register subsegT subseg;
367{
368#ifndef MANY_SEGMENTS
369 know (seg == SEG_DATA || seg == SEG_TEXT || seg == SEG_BSS);
370#endif
371
372 if (seg != now_seg || subseg != now_subseg)
373 { /* we just changed sub-segments */
374 subseg_set_rest (seg, subseg);
375 }
376}
377
378#else /* BFD_ASSEMBLER */
379
380segT
d025bc7b 381subseg_get (segname, force_new)
604633ae 382 const char *segname;
d025bc7b 383 int force_new;
604633ae
ILT
384{
385 segT secptr;
386 segment_info_type *seginfo;
387 const char *now_seg_name = (now_seg
388 ? bfd_get_section_name (stdoutput, now_seg)
389 : 0);
390
d025bc7b
JL
391 if (!force_new
392 && now_seg_name
604633ae 393 && (now_seg_name == segname
d025bc7b 394 || !strcmp (now_seg_name, segname)))
604633ae
ILT
395 return now_seg;
396
d025bc7b
JL
397 if (!force_new)
398 secptr = bfd_make_section_old_way (stdoutput, segname);
399 else
400 secptr = bfd_make_section_anyway (stdoutput, segname);
401
604633ae
ILT
402 seginfo = seg_info (secptr);
403 if (! seginfo)
404 {
405 secptr->output_section = secptr;
406 seginfo = (segment_info_type *) xmalloc (sizeof (*seginfo));
cc886e3d
SS
407 memset ((char *) seginfo, 0, sizeof(seginfo));
408 seginfo->fix_root = NULL;
604633ae
ILT
409 seginfo->bfd_section = secptr;
410 bfd_set_section_userdata (stdoutput, secptr, (char *) seginfo);
cc886e3d
SS
411 seginfo->frchainP = NULL;
412 seginfo->lineno_list_head = seginfo->lineno_list_tail = NULL;
413 seginfo->sym = NULL;
414 seginfo->dot = NULL;
604633ae 415 }
d025bc7b
JL
416 return secptr;
417}
418
419segT
420subseg_new (segname, subseg)
421 const char *segname;
422 subsegT subseg;
423{
424 segT secptr;
425 segment_info_type *seginfo;
426
427 secptr = subseg_get (segname, 0);
428 subseg_set_rest (secptr, subseg);
429 seginfo = seg_info (secptr);
430 if (! seginfo->frchainP)
431 seginfo->frchainP = frchain_now;
432 return secptr;
433}
434
435/* Like subseg_new, except a new section is always created, even if
436 a section with that name already exists. */
437segT
438subseg_force_new (segname, subseg)
439 const char *segname;
440 subsegT subseg;
441{
442 segT secptr;
443 segment_info_type *seginfo;
444
445 secptr = subseg_get (segname, 1);
446 subseg_set_rest (secptr, subseg);
447 seginfo = seg_info (secptr);
448 if (! seginfo->frchainP)
449 seginfo->frchainP = frchain_now;
604633ae
ILT
450 return secptr;
451}
452
453void
454subseg_set (secptr, subseg)
455 segT secptr;
456 subsegT subseg;
457{
458 if (! (secptr == now_seg && subseg == now_subseg))
459 subseg_set_rest (secptr, subseg);
460}
461
cc886e3d
SS
462#ifndef obj_sec_sym_ok_for_reloc
463#define obj_sec_sym_ok_for_reloc(SEC) 0
464#endif
465
d025bc7b
JL
466symbolS *
467section_symbol (sec)
468 segT sec;
469{
470 segment_info_type *seginfo = seg_info (sec);
cc886e3d 471 symbolS *s;
d025bc7b
JL
472
473 if (seginfo == 0)
474 abort ();
475 if (seginfo->sym)
476 return seginfo->sym;
cc886e3d
SS
477 s = symbol_find (sec->name);
478 if (!s)
d025bc7b 479 {
cc886e3d
SS
480 s = symbol_new (sec->name, sec, 0, &zero_address_frag);
481 S_CLEAR_EXTERNAL (s);
482
483 /* Use the BFD section symbol, if possible. */
484 if (obj_sec_sym_ok_for_reloc (sec))
485 s->bsym = sec->symbol;
d025bc7b 486 }
cc886e3d
SS
487 seginfo->sym = s;
488 return s;
d025bc7b
JL
489}
490
604633ae 491#endif /* BFD_ASSEMBLER */
fecd2382 492
8b228fe9 493/* end of subsegs.c */
This page took 0.13027 seconds and 4 git commands to generate.