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