Subversion Repositories Kolibri OS

Rev

Rev 5222 | Blame | Compare with Previous | Last modification | View Log | RSS feed

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