xref: /dflybsd-src/contrib/binutils-2.34/gas/subsegs.c (revision b52ef7118d1621abed722c5bbbd542210290ecef)
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