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