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