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