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