Back to index

cell-binutils  2.17cvs20070401
subsegs.c
Go to the documentation of this file.
00001 /* subsegs.c - subsegments -
00002    Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
00003    1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
00004    Free Software Foundation, Inc.
00005 
00006    This file is part of GAS, the GNU Assembler.
00007 
00008    GAS is free software; you can redistribute it and/or modify
00009    it under the terms of the GNU General Public License as published by
00010    the Free Software Foundation; either version 2, or (at your option)
00011    any later version.
00012 
00013    GAS is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016    GNU General Public License for more details.
00017 
00018    You should have received a copy of the GNU General Public License
00019    along with GAS; see the file COPYING.  If not, write to the Free
00020    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
00021    02110-1301, USA.  */
00022 
00023 /* Segments & sub-segments.  */
00024 
00025 #include "as.h"
00026 
00027 #include "subsegs.h"
00028 #include "obstack.h"
00029 
00030 frchainS *frchain_now;
00031 
00032 static struct obstack frchains;
00033 
00034 static fragS dummy_frag;
00035 
00036 
00037 void
00038 subsegs_begin (void)
00039 {
00040   obstack_begin (&frchains, chunksize);
00041 #if __GNUC__ >= 2
00042   obstack_alignment_mask (&frchains) = __alignof__ (frchainS) - 1;
00043 #endif
00044 
00045   frchain_now = NULL;              /* Warn new_subseg() that we are booting.  */
00046   frag_now = &dummy_frag;
00047 }
00048 
00049 /*
00050  *                   subseg_change()
00051  *
00052  * Change the subsegment we are in, BUT DO NOT MAKE A NEW FRAG for the
00053  * subsegment. If we are already in the correct subsegment, change nothing.
00054  * This is used eg as a worker for subseg_set [which does make a new frag_now]
00055  * and for changing segments after we have read the source. We construct eg
00056  * fixSs even after the source file is read, so we do have to keep the
00057  * segment context correct.
00058  */
00059 void
00060 subseg_change (register segT seg, register int subseg)
00061 {
00062   segment_info_type *seginfo = seg_info (seg);
00063   now_seg = seg;
00064   now_subseg = subseg;
00065 
00066   if (! seginfo)
00067     {
00068       seginfo = xcalloc (1, sizeof (*seginfo));
00069       seginfo->bfd_section = seg;
00070       bfd_set_section_userdata (stdoutput, seg, seginfo);
00071     }
00072 }
00073 
00074 static void
00075 subseg_set_rest (segT seg, subsegT subseg)
00076 {
00077   frchainS *frcP;           /* crawl frchain chain */
00078   frchainS **lastPP;        /* address of last pointer */
00079   frchainS *newP;           /* address of new frchain */
00080   segment_info_type *seginfo;
00081 
00082   mri_common_symbol = NULL;
00083 
00084   if (frag_now && frchain_now)
00085     frchain_now->frch_frag_now = frag_now;
00086 
00087   assert (frchain_now == 0
00088          || frchain_now->frch_last == frag_now);
00089 
00090   subseg_change (seg, (int) subseg);
00091 
00092   seginfo = seg_info (seg);
00093 
00094   /* Attempt to find or make a frchain for that subsection.
00095      We keep the list sorted by subsection number.  */
00096   for (frcP = *(lastPP = &seginfo->frchainP);
00097        frcP != NULL;
00098        frcP = *(lastPP = &frcP->frch_next))
00099     if (frcP->frch_subseg >= subseg)
00100       break;
00101 
00102   if (frcP == NULL || frcP->frch_subseg != subseg)
00103     {
00104       /* This should be the only code that creates a frchainS.  */
00105 
00106       newP = obstack_alloc (&frchains, sizeof (frchainS));
00107       newP->frch_subseg = subseg;
00108       newP->fix_root = NULL;
00109       newP->fix_tail = NULL;
00110       obstack_begin (&newP->frch_obstack, chunksize);
00111 #if __GNUC__ >= 2
00112       obstack_alignment_mask (&newP->frch_obstack) = __alignof__ (fragS) - 1;
00113 #endif
00114       newP->frch_frag_now = frag_alloc (&newP->frch_obstack);
00115       newP->frch_frag_now->fr_type = rs_fill;
00116       newP->frch_cfi_data = NULL;
00117 
00118       newP->frch_root = newP->frch_last = newP->frch_frag_now;
00119 
00120       *lastPP = newP;
00121       newP->frch_next = frcP;
00122       frcP = newP;
00123     }
00124 
00125   frchain_now = frcP;
00126   frag_now = frcP->frch_frag_now;
00127 
00128   assert (frchain_now->frch_last == frag_now);
00129 }
00130 
00131 /*
00132  *                   subseg_set(segT, subsegT)
00133  *
00134  * If you attempt to change to the current subsegment, nothing happens.
00135  *
00136  * In: segT, subsegT code for new subsegment.
00137  *     frag_now -> incomplete frag for current subsegment.
00138  *     If frag_now==NULL, then there is no old, incomplete frag, so
00139  *     the old frag is not closed off.
00140  *
00141  * Out:       now_subseg, now_seg updated.
00142  *     Frchain_now points to the (possibly new) struct frchain for this
00143  *     sub-segment.
00144  */
00145 
00146 segT
00147 subseg_get (const char *segname, int force_new)
00148 {
00149   segT secptr;
00150   segment_info_type *seginfo;
00151   const char *now_seg_name = (now_seg
00152                            ? bfd_get_section_name (stdoutput, now_seg)
00153                            : 0);
00154 
00155   if (!force_new
00156       && now_seg_name
00157       && (now_seg_name == segname
00158          || !strcmp (now_seg_name, segname)))
00159     return now_seg;
00160 
00161   if (!force_new)
00162     secptr = bfd_make_section_old_way (stdoutput, segname);
00163   else
00164     secptr = bfd_make_section_anyway (stdoutput, segname);
00165 
00166   seginfo = seg_info (secptr);
00167   if (! seginfo)
00168     {
00169       secptr->output_section = secptr;
00170       seginfo = xcalloc (1, sizeof (*seginfo));
00171       seginfo->bfd_section = secptr;
00172       bfd_set_section_userdata (stdoutput, secptr, seginfo);
00173     }
00174   return secptr;
00175 }
00176 
00177 segT
00178 subseg_new (const char *segname, subsegT subseg)
00179 {
00180   segT secptr;
00181 
00182   secptr = subseg_get (segname, 0);
00183   subseg_set_rest (secptr, subseg);
00184   return secptr;
00185 }
00186 
00187 /* Like subseg_new, except a new section is always created, even if
00188    a section with that name already exists.  */
00189 segT
00190 subseg_force_new (const char *segname, subsegT subseg)
00191 {
00192   segT secptr;
00193 
00194   secptr = subseg_get (segname, 1);
00195   subseg_set_rest (secptr, subseg);
00196   return secptr;
00197 }
00198 
00199 void
00200 subseg_set (segT secptr, subsegT subseg)
00201 {
00202   if (! (secptr == now_seg && subseg == now_subseg))
00203     subseg_set_rest (secptr, subseg);
00204   mri_common_symbol = NULL;
00205 }
00206 
00207 #ifndef obj_sec_sym_ok_for_reloc
00208 #define obj_sec_sym_ok_for_reloc(SEC)     0
00209 #endif
00210 
00211 symbolS *
00212 section_symbol (segT sec)
00213 {
00214   segment_info_type *seginfo = seg_info (sec);
00215   symbolS *s;
00216 
00217   if (seginfo == 0)
00218     abort ();
00219   if (seginfo->sym)
00220     return seginfo->sym;
00221 
00222 #ifndef EMIT_SECTION_SYMBOLS
00223 #define EMIT_SECTION_SYMBOLS 1
00224 #endif
00225 
00226   if (! EMIT_SECTION_SYMBOLS || symbol_table_frozen)
00227     {
00228       /* Here we know it won't be going into the symbol table.  */
00229       s = symbol_create (sec->symbol->name, sec, 0, &zero_address_frag);
00230     }
00231   else
00232     {
00233       segT seg;
00234       s = symbol_find (sec->symbol->name);
00235       /* We have to make sure it is the right symbol when we
00236         have multiple sections with the same section name.  */
00237       if (s == NULL
00238          || ((seg = S_GET_SEGMENT (s)) != sec
00239              && seg != undefined_section))
00240        s = symbol_new (sec->symbol->name, sec, 0, &zero_address_frag);
00241       else if (seg == undefined_section)
00242        {
00243          S_SET_SEGMENT (s, sec);
00244          symbol_set_frag (s, &zero_address_frag);
00245        }
00246     }
00247 
00248   S_CLEAR_EXTERNAL (s);
00249 
00250   /* Use the BFD section symbol, if possible.  */
00251   if (obj_sec_sym_ok_for_reloc (sec))
00252     symbol_set_bfdsym (s, sec->symbol);
00253   else
00254     symbol_get_bfdsym (s)->flags |= BSF_SECTION_SYM;
00255 
00256   seginfo->sym = s;
00257   return s;
00258 }
00259 
00260 /* Return whether the specified segment is thought to hold text.  */
00261 
00262 int
00263 subseg_text_p (segT sec)
00264 {
00265   return (bfd_get_section_flags (stdoutput, sec) & SEC_CODE) != 0;
00266 }
00267 
00268 /* Return non zero if SEC has at least one byte of data.  It is
00269    possible that we'll return zero even on a non-empty section because
00270    we don't know all the fragment types, and it is possible that an
00271    fr_fix == 0 one still contributes data.  Think of this as
00272    seg_definitely_not_empty_p.  */
00273 
00274 int
00275 seg_not_empty_p (segT sec ATTRIBUTE_UNUSED)
00276 {
00277   segment_info_type *seginfo = seg_info (sec);
00278   frchainS *chain;
00279   fragS *frag;
00280 
00281   if (!seginfo)
00282     return 0;
00283   
00284   for (chain = seginfo->frchainP; chain; chain = chain->frch_next)
00285     {
00286       for (frag = chain->frch_root; frag; frag = frag->fr_next)
00287        if (frag->fr_fix)
00288          return 1;
00289       if (obstack_next_free (&chain->frch_obstack)
00290          != chain->frch_last->fr_literal)
00291        return 1;
00292     }
00293   return 0;
00294 }
00295 
00296 void
00297 subsegs_print_statistics (FILE *file)
00298 {
00299   frchainS *frchp;
00300   asection *s;
00301 
00302   fprintf (file, "frag chains:\n");
00303   for (s = stdoutput->sections; s; s = s->next)
00304     {
00305       segment_info_type *seginfo;
00306 
00307       /* Skip gas-internal sections.  */
00308       if (segment_name (s)[0] == '*')
00309        continue;
00310 
00311       seginfo = seg_info (s);
00312       if (!seginfo)
00313        continue;
00314 
00315       for (frchp = seginfo->frchainP; frchp; frchp = frchp->frch_next)
00316        {
00317          int count = 0;
00318          fragS *fragp;
00319 
00320          for (fragp = frchp->frch_root; fragp; fragp = fragp->fr_next)
00321            count++;
00322 
00323          fprintf (file, "\n");
00324          fprintf (file, "\t%p %-10s\t%10d frags\n", (void *) frchp,
00325                  segment_name (s), count);
00326        }
00327     }
00328 }
00329 
00330 /* end of subsegs.c */