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