ChangeLog:
[deliverable/binutils-gdb.git] / gas / subsegs.c
CommitLineData
252b5132 1/* subsegs.c - subsegments -
f7e42eb4 2 Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
e7ff5c73 3 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
252b5132
RH
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
ec2655a6 10 the Free Software Foundation; either version 3, or (at your option)
252b5132
RH
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
4b4da160
NC
20 Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
21 02110-1301, USA. */
252b5132 22
ef99799a 23/* Segments & sub-segments. */
252b5132
RH
24
25#include "as.h"
26
27#include "subsegs.h"
28#include "obstack.h"
29
c9049d30 30frchainS *frchain_now;
252b5132
RH
31
32static struct obstack frchains;
33
252b5132
RH
34static fragS dummy_frag;
35
252b5132
RH
36\f
37void
24361518 38subsegs_begin (void)
252b5132 39{
252b5132
RH
40 obstack_begin (&frchains, chunksize);
41#if __GNUC__ >= 2
42 obstack_alignment_mask (&frchains) = __alignof__ (frchainS) - 1;
43#endif
44
f0e652b4 45 frchain_now = NULL; /* Warn new_subseg() that we are booting. */
252b5132 46 frag_now = &dummy_frag;
252b5132
RH
47}
48\f
49/*
50 * subseg_change()
51 *
52 * Change the subsegment we are in, BUT DO NOT MAKE A NEW FRAG for the
53 * subsegment. If we are already in the correct subsegment, change nothing.
54 * This is used eg as a worker for subseg_set [which does make a new frag_now]
55 * and for changing segments after we have read the source. We construct eg
56 * fixSs even after the source file is read, so we do have to keep the
57 * segment context correct.
58 */
59void
24361518 60subseg_change (register segT seg, register int subseg)
252b5132 61{
c9049d30 62 segment_info_type *seginfo = seg_info (seg);
252b5132
RH
63 now_seg = seg;
64 now_subseg = subseg;
65
7be1c489 66 if (! seginfo)
252b5132 67 {
e7ff5c73 68 seginfo = xcalloc (1, sizeof (*seginfo));
7be1c489 69 seginfo->bfd_section = seg;
e7ff5c73 70 bfd_set_section_userdata (stdoutput, seg, seginfo);
252b5132 71 }
252b5132
RH
72}
73\f
74static void
24361518 75subseg_set_rest (segT seg, subsegT subseg)
252b5132 76{
c9049d30
AM
77 frchainS *frcP; /* crawl frchain chain */
78 frchainS **lastPP; /* address of last pointer */
252b5132 79 frchainS *newP; /* address of new frchain */
c9049d30 80 segment_info_type *seginfo;
252b5132
RH
81
82 mri_common_symbol = NULL;
83
84 if (frag_now && frchain_now)
85 frchain_now->frch_frag_now = frag_now;
86
9c2799c2 87 gas_assert (frchain_now == 0
252b5132
RH
88 || frchain_now->frch_last == frag_now);
89
90 subseg_change (seg, (int) subseg);
91
c9049d30 92 seginfo = seg_info (seg);
252b5132 93
c9049d30
AM
94 /* Attempt to find or make a frchain for that subsection.
95 We keep the list sorted by subsection number. */
96 for (frcP = *(lastPP = &seginfo->frchainP);
97 frcP != NULL;
252b5132 98 frcP = *(lastPP = &frcP->frch_next))
c9049d30
AM
99 if (frcP->frch_subseg >= subseg)
100 break;
101
102 if (frcP == NULL || frcP->frch_subseg != subseg)
252b5132 103 {
c9049d30 104 /* This should be the only code that creates a frchainS. */
7be1c489 105
e7ff5c73 106 newP = obstack_alloc (&frchains, sizeof (frchainS));
252b5132 107 newP->frch_subseg = subseg;
252b5132
RH
108 newP->fix_root = NULL;
109 newP->fix_tail = NULL;
252b5132
RH
110 obstack_begin (&newP->frch_obstack, chunksize);
111#if __GNUC__ >= 2
112 obstack_alignment_mask (&newP->frch_obstack) = __alignof__ (fragS) - 1;
113#endif
114 newP->frch_frag_now = frag_alloc (&newP->frch_obstack);
115 newP->frch_frag_now->fr_type = rs_fill;
5fd396ba 116 newP->frch_cfi_data = NULL;
252b5132
RH
117
118 newP->frch_root = newP->frch_last = newP->frch_frag_now;
119
120 *lastPP = newP;
c9049d30 121 newP->frch_next = frcP;
252b5132
RH
122 frcP = newP;
123 }
c9049d30 124
252b5132
RH
125 frchain_now = frcP;
126 frag_now = frcP->frch_frag_now;
127
9c2799c2 128 gas_assert (frchain_now->frch_last == frag_now);
252b5132
RH
129}
130
131/*
132 * subseg_set(segT, subsegT)
133 *
134 * If you attempt to change to the current subsegment, nothing happens.
135 *
136 * In: segT, subsegT code for new subsegment.
137 * frag_now -> incomplete frag for current subsegment.
138 * If frag_now==NULL, then there is no old, incomplete frag, so
139 * the old frag is not closed off.
140 *
141 * Out: now_subseg, now_seg updated.
142 * Frchain_now points to the (possibly new) struct frchain for this
143 * sub-segment.
252b5132
RH
144 */
145
252b5132 146segT
24361518 147subseg_get (const char *segname, int force_new)
252b5132
RH
148{
149 segT secptr;
150 segment_info_type *seginfo;
151 const char *now_seg_name = (now_seg
152 ? bfd_get_section_name (stdoutput, now_seg)
153 : 0);
154
155 if (!force_new
156 && now_seg_name
157 && (now_seg_name == segname
158 || !strcmp (now_seg_name, segname)))
159 return now_seg;
160
161 if (!force_new)
162 secptr = bfd_make_section_old_way (stdoutput, segname);
163 else
164 secptr = bfd_make_section_anyway (stdoutput, segname);
165
166 seginfo = seg_info (secptr);
167 if (! seginfo)
168 {
c9049d30 169 secptr->output_section = secptr;
e7ff5c73 170 seginfo = xcalloc (1, sizeof (*seginfo));
252b5132 171 seginfo->bfd_section = secptr;
e7ff5c73 172 bfd_set_section_userdata (stdoutput, secptr, seginfo);
252b5132
RH
173 }
174 return secptr;
175}
176
177segT
24361518 178subseg_new (const char *segname, subsegT subseg)
252b5132
RH
179{
180 segT secptr;
252b5132
RH
181
182 secptr = subseg_get (segname, 0);
183 subseg_set_rest (secptr, subseg);
252b5132
RH
184 return secptr;
185}
186
187/* Like subseg_new, except a new section is always created, even if
188 a section with that name already exists. */
189segT
24361518 190subseg_force_new (const char *segname, subsegT subseg)
252b5132
RH
191{
192 segT secptr;
252b5132
RH
193
194 secptr = subseg_get (segname, 1);
195 subseg_set_rest (secptr, subseg);
252b5132
RH
196 return secptr;
197}
198
199void
24361518 200subseg_set (segT secptr, subsegT subseg)
252b5132
RH
201{
202 if (! (secptr == now_seg && subseg == now_subseg))
203 subseg_set_rest (secptr, subseg);
204 mri_common_symbol = NULL;
205}
206
207#ifndef obj_sec_sym_ok_for_reloc
208#define obj_sec_sym_ok_for_reloc(SEC) 0
209#endif
210
252b5132 211symbolS *
24361518 212section_symbol (segT sec)
252b5132
RH
213{
214 segment_info_type *seginfo = seg_info (sec);
215 symbolS *s;
216
217 if (seginfo == 0)
218 abort ();
219 if (seginfo->sym)
220 return seginfo->sym;
221
222#ifndef EMIT_SECTION_SYMBOLS
223#define EMIT_SECTION_SYMBOLS 1
224#endif
225
a161fe53 226 if (! EMIT_SECTION_SYMBOLS || symbol_table_frozen)
252b5132
RH
227 {
228 /* Here we know it won't be going into the symbol table. */
546c73f9 229 s = symbol_create (sec->symbol->name, sec, 0, &zero_address_frag);
252b5132
RH
230 }
231 else
232 {
90c1602c 233 segT seg;
91c4c449 234 s = symbol_find (sec->symbol->name);
22fe14ad
NC
235 /* We have to make sure it is the right symbol when we
236 have multiple sections with the same section name. */
90c1602c
L
237 if (s == NULL
238 || ((seg = S_GET_SEGMENT (s)) != sec
239 && seg != undefined_section))
546c73f9 240 s = symbol_new (sec->symbol->name, sec, 0, &zero_address_frag);
90c1602c 241 else if (seg == undefined_section)
252b5132 242 {
90c1602c
L
243 S_SET_SEGMENT (s, sec);
244 symbol_set_frag (s, &zero_address_frag);
252b5132
RH
245 }
246 }
247
248 S_CLEAR_EXTERNAL (s);
249
250 /* Use the BFD section symbol, if possible. */
251 if (obj_sec_sym_ok_for_reloc (sec))
49309057 252 symbol_set_bfdsym (s, sec->symbol);
a161fe53
AM
253 else
254 symbol_get_bfdsym (s)->flags |= BSF_SECTION_SYM;
252b5132
RH
255
256 seginfo->sym = s;
257 return s;
258}
259
b9e57a38
ILT
260/* Return whether the specified segment is thought to hold text. */
261
262int
24361518 263subseg_text_p (segT sec)
b9e57a38 264{
b9e57a38 265 return (bfd_get_section_flags (stdoutput, sec) & SEC_CODE) != 0;
b9e57a38
ILT
266}
267
c6cb92c5
NS
268/* Return non zero if SEC has at least one byte of data. It is
269 possible that we'll return zero even on a non-empty section because
270 we don't know all the fragment types, and it is possible that an
271 fr_fix == 0 one still contributes data. Think of this as
272 seg_definitely_not_empty_p. */
273
4ee4d249 274int
f17c130b 275seg_not_empty_p (segT sec ATTRIBUTE_UNUSED)
c6cb92c5
NS
276{
277 segment_info_type *seginfo = seg_info (sec);
278 frchainS *chain;
279 fragS *frag;
280
281 if (!seginfo)
282 return 0;
283
284 for (chain = seginfo->frchainP; chain; chain = chain->frch_next)
285 {
286 for (frag = chain->frch_root; frag; frag = frag->fr_next)
287 if (frag->fr_fix)
288 return 1;
289 if (obstack_next_free (&chain->frch_obstack)
290 != chain->frch_last->fr_literal)
291 return 1;
292 }
293 return 0;
294}
295
252b5132 296void
24361518 297subsegs_print_statistics (FILE *file)
252b5132
RH
298{
299 frchainS *frchp;
c9049d30
AM
300 asection *s;
301
252b5132 302 fprintf (file, "frag chains:\n");
c9049d30 303 for (s = stdoutput->sections; s; s = s->next)
252b5132 304 {
c9049d30 305 segment_info_type *seginfo;
252b5132 306
c9049d30
AM
307 /* Skip gas-internal sections. */
308 if (segment_name (s)[0] == '*')
252b5132
RH
309 continue;
310
c9049d30
AM
311 seginfo = seg_info (s);
312 if (!seginfo)
252b5132
RH
313 continue;
314
c9049d30 315 for (frchp = seginfo->frchainP; frchp; frchp = frchp->frch_next)
252b5132 316 {
c9049d30
AM
317 int count = 0;
318 fragS *fragp;
319
320 for (fragp = frchp->frch_root; fragp; fragp = fragp->fr_next)
321 count++;
322
323 fprintf (file, "\n");
324 fprintf (file, "\t%p %-10s\t%10d frags\n", (void *) frchp,
325 segment_name (s), count);
252b5132 326 }
252b5132
RH
327 }
328}
329
330/* end of subsegs.c */
This page took 0.440032 seconds and 4 git commands to generate.