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