home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / binutils-2.7-src.tgz / tar.out / fsf / binutils / gas / subsegs.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  15KB  |  595 lines

  1. /* subsegs.c - subsegments -
  2.    Copyright (C) 1987, 90, 91, 92, 93, 94, 95, 1996
  3.    Free Software Foundation, Inc.
  4.  
  5.    This file is part of GAS, the GNU Assembler.
  6.  
  7.    GAS is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 2, or (at your option)
  10.    any later version.
  11.  
  12.    GAS is distributed in the hope that it will be useful,
  13.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.    GNU General Public License for more details.
  16.  
  17.    You should have received a copy of the GNU General Public License
  18.    along with GAS; see the file COPYING.  If not, write to the Free
  19.    Software Foundation, 59 Temple Place - Suite 330, Boston, MA
  20.    02111-1307, USA.  */
  21.  
  22. /*
  23.  * Segments & sub-segments.
  24.  */
  25.  
  26. #include "as.h"
  27.  
  28. #include "subsegs.h"
  29. #include "obstack.h"
  30.  
  31. frchainS *frchain_root, *frchain_now;
  32.  
  33. static struct obstack frchains;
  34.  
  35. #ifndef BFD_ASSEMBLER
  36. #ifdef MANY_SEGMENTS
  37. segment_info_type segment_info[SEG_MAXIMUM_ORDINAL];
  38.  
  39. #else
  40. /* Commented in "subsegs.h". */
  41. frchainS *data0_frchainP, *bss0_frchainP;
  42.  
  43. #endif /* MANY_SEGMENTS */
  44. char const *const seg_name[] =
  45. {
  46.   "absolute",
  47. #ifdef MANY_SEGMENTS
  48.   "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9",
  49.   "e10", "e11", "e12", "e13", "e14", "e15", "e16", "e17", "e18", "e19",
  50.   "e20", "e21", "e22", "e23", "e24", "e25", "e26", "e27", "e28", "e29",
  51.   "e30", "e31", "e32", "e33", "e34", "e35", "e36", "e37", "e38", "e39",
  52. #else
  53.   "text",
  54.   "data",
  55.   "bss",
  56. #endif /* MANY_SEGMENTS */
  57.   "unknown",
  58.   "ASSEMBLER-INTERNAL-LOGIC-ERROR!",
  59.   "expr",
  60.   "debug",
  61.   "transfert vector preload",
  62.   "transfert vector postload",
  63.   "register",
  64.   "",
  65. };                /* Used by error reporters, dumpers etc. */
  66. #else /* BFD_ASSEMBLER */
  67.  
  68. /* Gas segment information for bfd_abs_section_ptr and
  69.    bfd_und_section_ptr.  */
  70. static segment_info_type *abs_seg_info;
  71. static segment_info_type *und_seg_info;
  72.  
  73. #endif /* BFD_ASSEMBLER */
  74.  
  75. static void subseg_set_rest PARAMS ((segT, subsegT));
  76.  
  77. static fragS dummy_frag;
  78.  
  79. static frchainS absolute_frchain;
  80.  
  81. void
  82. subsegs_begin ()
  83. {
  84.   /* Check table(s) seg_name[], seg_N_TYPE[] is in correct order */
  85. #if !defined (MANY_SEGMENTS) && !defined (BFD_ASSEMBLER)
  86.   know (SEG_ABSOLUTE == 0);
  87.   know (SEG_TEXT == 1);
  88.   know (SEG_DATA == 2);
  89.   know (SEG_BSS == 3);
  90.   know (SEG_UNKNOWN == 4);
  91.   know (SEG_GOOF == 5);
  92.   know (SEG_EXPR == 6);
  93.   know (SEG_DEBUG == 7);
  94.   know (SEG_NTV == 8);
  95.   know (SEG_PTV == 9);
  96.   know (SEG_REGISTER == 10);
  97.   know (SEG_MAXIMUM_ORDINAL == SEG_REGISTER);
  98. #endif
  99.  
  100.   obstack_begin (&frchains, chunksize);
  101. #if __GNUC__ >= 2
  102.   obstack_alignment_mask (&frchains) = __alignof__ (frchainS) - 1;
  103. #endif
  104.  
  105.   frchain_root = NULL;
  106.   frchain_now = NULL;        /* Warn new_subseg() that we are booting. */
  107.  
  108.   frag_now = &dummy_frag;
  109.  
  110. #ifndef BFD_ASSEMBLER
  111.   now_subseg = 42;        /* Lie for 1st call to subseg_new. */
  112. #ifdef MANY_SEGMENTS
  113.   {
  114.     int i;
  115.     for (i = SEG_E0; i < SEG_UNKNOWN; i++)
  116.       {
  117.     subseg_set (i, 0);
  118.     segment_info[i].frchainP = frchain_now;
  119.       }
  120.   }
  121. #else
  122.   subseg_set (SEG_DATA, 0);    /* .data 0 */
  123.   data0_frchainP = frchain_now;
  124.  
  125.   subseg_set (SEG_BSS, 0);
  126.   bss0_frchainP = frchain_now;
  127.  
  128. #endif /* ! MANY_SEGMENTS */
  129. #endif /* ! BFD_ASSEMBLER */
  130.  
  131.   absolute_frchain.frch_seg = absolute_section;
  132.   absolute_frchain.frch_subseg = 0;
  133. #ifdef BFD_ASSEMBLER
  134.   absolute_frchain.fix_root = absolute_frchain.fix_tail = 0;
  135. #endif
  136.   absolute_frchain.frch_frag_now = &zero_address_frag;
  137.   absolute_frchain.frch_root = absolute_frchain.frch_last = &zero_address_frag;
  138. }
  139.  
  140. /*
  141.  *            subseg_change()
  142.  *
  143.  * Change the subsegment we are in, BUT DO NOT MAKE A NEW FRAG for the
  144.  * subsegment. If we are already in the correct subsegment, change nothing.
  145.  * This is used eg as a worker for subseg_set [which does make a new frag_now]
  146.  * and for changing segments after we have read the source. We construct eg
  147.  * fixSs even after the source file is read, so we do have to keep the
  148.  * segment context correct.
  149.  */
  150. void
  151. subseg_change (seg, subseg)
  152.      register segT seg;
  153.      register int subseg;
  154. {
  155.   now_seg = seg;
  156.   now_subseg = subseg;
  157.  
  158.   if (now_seg == absolute_section)
  159.     return;
  160.  
  161. #ifdef BFD_ASSEMBLER
  162.   {
  163.     segment_info_type *seginfo;
  164.     seginfo = (segment_info_type *) bfd_get_section_userdata (stdoutput, seg);
  165.     if (! seginfo)
  166.       {
  167.     seginfo = (segment_info_type *) xmalloc (sizeof (*seginfo));
  168.     memset ((PTR) seginfo, 0, sizeof (*seginfo));
  169.     seginfo->fix_root = NULL;
  170.     seginfo->fix_tail = NULL;
  171.     seginfo->bfd_section = seg;
  172.     seginfo->sym = 0;
  173.     if (seg == bfd_abs_section_ptr)
  174.       abs_seg_info = seginfo;
  175.     else if (seg == bfd_und_section_ptr)
  176.       und_seg_info = seginfo;
  177.     else
  178.       bfd_set_section_userdata (stdoutput, seg, (PTR) seginfo);
  179.       }
  180.   }
  181. #else
  182. #ifdef MANY_SEGMENTS
  183.   seg_fix_rootP = &segment_info[seg].fix_root;
  184.   seg_fix_tailP = &segment_info[seg].fix_tail;
  185. #else
  186.   if (seg == SEG_DATA)
  187.     {
  188.       seg_fix_rootP = &data_fix_root;
  189.       seg_fix_tailP = &data_fix_tail;
  190.     }
  191.   else if (seg == SEG_TEXT)
  192.     {
  193.       seg_fix_rootP = &text_fix_root;
  194.       seg_fix_tailP = &text_fix_tail;
  195.     }
  196.   else
  197.     {
  198.       know (seg == SEG_BSS);
  199.       seg_fix_rootP = &bss_fix_root;
  200.       seg_fix_tailP = &bss_fix_tail;
  201.     }
  202.  
  203. #endif
  204. #endif
  205. }
  206.  
  207. static void
  208. subseg_set_rest (seg, subseg)
  209.      segT seg;
  210.      subsegT subseg;
  211. {
  212.   register frchainS *frcP;    /* crawl frchain chain */
  213.   register frchainS **lastPP;    /* address of last pointer */
  214.   frchainS *newP;        /* address of new frchain */
  215.  
  216.   mri_common_symbol = NULL;
  217.  
  218.   if (frag_now && frchain_now)
  219.     frchain_now->frch_frag_now = frag_now;
  220.  
  221.   assert (frchain_now == 0
  222.       || now_seg == undefined_section
  223.       || now_seg == absolute_section
  224.       || frchain_now->frch_last == frag_now);
  225.  
  226.   subseg_change (seg, (int) subseg);
  227.  
  228.   if (seg == absolute_section)
  229.     {
  230.       frchain_now = &absolute_frchain;
  231.       frag_now = &zero_address_frag;
  232.       return;
  233.     }
  234.  
  235.   assert (frchain_now == 0
  236.       || now_seg == undefined_section
  237.       || frchain_now->frch_last == frag_now);
  238.  
  239.   /*
  240.    * Attempt to find or make a frchain for that sub seg.
  241.    * Crawl along chain of frchainSs, begins @ frchain_root.
  242.    * If we need to make a frchainS, link it into correct
  243.    * position of chain rooted in frchain_root.
  244.    */
  245.   for (frcP = *(lastPP = &frchain_root);
  246.        frcP && frcP->frch_seg <= seg;
  247.        frcP = *(lastPP = &frcP->frch_next))
  248.     {
  249.       if (frcP->frch_seg == seg
  250.       && frcP->frch_subseg >= subseg)
  251.     {
  252.       break;
  253.     }
  254.     }
  255.   /*
  256.    * frcP:        Address of the 1st frchainS in correct segment with
  257.    *        frch_subseg >= subseg.
  258.    *        We want to either use this frchainS, or we want
  259.    *        to insert a new frchainS just before it.
  260.    *
  261.    *        If frcP==NULL, then we are at the end of the chain
  262.    *        of frchainS-s. A NULL frcP means we fell off the end
  263.    *        of the chain looking for a
  264.    *        frch_subseg >= subseg, so we
  265.    *        must make a new frchainS.
  266.    *
  267.    *        If we ever maintain a pointer to
  268.    *        the last frchainS in the chain, we change that pointer
  269.    *        ONLY when frcP==NULL.
  270.    *
  271.    * lastPP:    Address of the pointer with value frcP;
  272.    *        Never NULL.
  273.    *        May point to frchain_root.
  274.    *
  275.    */
  276.   if (!frcP
  277.       || (frcP->frch_seg > seg
  278.       || frcP->frch_subseg > subseg))    /* Kinky logic only works with 2 segments. */
  279.     {
  280.       /*
  281.        * This should be the only code that creates a frchainS.
  282.        */
  283.       extern fragS *frag_alloc ();
  284.       newP = (frchainS *) obstack_alloc (&frchains, sizeof (frchainS));
  285.       newP->frch_subseg = subseg;
  286.       newP->frch_seg = seg;
  287. #ifdef BFD_ASSEMBLER
  288.       newP->fix_root = NULL;
  289.       newP->fix_tail = NULL;
  290. #endif
  291.       obstack_begin (&newP->frch_obstack, 5000);
  292. #if __GNUC__ >= 2
  293.       obstack_alignment_mask (&newP->frch_obstack) = __alignof__ (fragS) - 1;
  294. #endif
  295.       newP->frch_frag_now = frag_alloc (&newP->frch_obstack);
  296.       newP->frch_frag_now->fr_type = rs_fill;
  297.  
  298.       newP->frch_root = newP->frch_last = newP->frch_frag_now;
  299.  
  300.       *lastPP = newP;
  301.       newP->frch_next = frcP;    /* perhaps NULL */
  302.       frcP = newP;
  303.     }
  304.   /*
  305.    * Here with frcP pointing to the frchainS for subseg.
  306.    */
  307.   frchain_now = frcP;
  308.   frag_now = frcP->frch_frag_now;
  309.  
  310.   assert (frchain_now->frch_last == frag_now);
  311. }
  312.  
  313. /*
  314.  *            subseg_set(segT, subsegT)
  315.  *
  316.  * If you attempt to change to the current subsegment, nothing happens.
  317.  *
  318.  * In:    segT, subsegT code for new subsegment.
  319.  *    frag_now -> incomplete frag for current subsegment.
  320.  *    If frag_now==NULL, then there is no old, incomplete frag, so
  321.  *    the old frag is not closed off.
  322.  *
  323.  * Out:    now_subseg, now_seg updated.
  324.  *    Frchain_now points to the (possibly new) struct frchain for this
  325.  *    sub-segment.
  326.  *    Frchain_root updated if needed.
  327.  */
  328.  
  329. #ifndef BFD_ASSEMBLER
  330.  
  331. segT
  332. subseg_new (segname, subseg)
  333.      const char *segname;
  334.      subsegT subseg;
  335. {
  336.   int i;
  337.  
  338.   for (i = 0; i < (int) SEG_MAXIMUM_ORDINAL; i++)
  339.     {
  340.       const char *s;
  341.  
  342.       s = segment_name ((segT) i);
  343.       if (strcmp (segname, s) == 0
  344.       || (segname[0] == '.'
  345.           && strcmp (segname + 1, s) == 0))
  346.     {
  347.       subseg_set ((segT) i, subseg);
  348.       return (segT) i;
  349.     }
  350. #ifdef obj_segment_name
  351.       s = obj_segment_name ((segT) i);
  352.       if (strcmp (segname, s) == 0
  353.       || (segname[0] == '.'
  354.           && strcmp (segname + 1, s) == 0))
  355.     {
  356.       subseg_set ((segT) i, subseg);
  357.       return (segT) i;
  358.     }
  359. #endif
  360.     }
  361.  
  362. #ifdef obj_add_segment
  363.   {
  364.     segT new_seg;
  365.     new_seg = obj_add_segment (segname);
  366.     subseg_set (new_seg, subseg);
  367.     return new_seg;
  368.   }
  369. #else
  370.   as_bad ("Attempt to switch to nonexistent segment \"%s\"", segname);
  371.   return now_seg;
  372. #endif
  373. }
  374.  
  375. void
  376. subseg_set (seg, subseg)    /* begin assembly for a new sub-segment */
  377.      register segT seg;        /* SEG_DATA or SEG_TEXT */
  378.      register subsegT subseg;
  379. {
  380. #ifndef MANY_SEGMENTS
  381.   know (seg == SEG_DATA
  382.     || seg == SEG_TEXT
  383.     || seg == SEG_BSS
  384.     || seg == SEG_ABSOLUTE);
  385. #endif
  386.  
  387.   if (seg != now_seg || subseg != now_subseg)
  388.     {                /* we just changed sub-segments */
  389.       subseg_set_rest (seg, subseg);
  390.     }
  391.   mri_common_symbol = NULL;
  392. }
  393.  
  394. #else /* BFD_ASSEMBLER */
  395.  
  396. segT
  397. subseg_get (segname, force_new)
  398.      const char *segname;
  399.      int force_new;
  400. {
  401.   segT secptr;
  402.   segment_info_type *seginfo;
  403.   const char *now_seg_name = (now_seg
  404.                   ? bfd_get_section_name (stdoutput, now_seg)
  405.                   : 0);
  406.  
  407.   if (!force_new
  408.       && now_seg_name
  409.       && (now_seg_name == segname
  410.       || !strcmp (now_seg_name, segname)))
  411.     return now_seg;
  412.  
  413.   if (!force_new)
  414.     secptr = bfd_make_section_old_way (stdoutput, segname);
  415.   else
  416.     secptr = bfd_make_section_anyway (stdoutput, segname);
  417.  
  418.   seginfo = seg_info (secptr);
  419.   if (! seginfo)
  420.     {
  421.       /* Check whether output_section is set first because secptr may
  422.          be bfd_abs_section_ptr.  */
  423.       if (secptr->output_section != secptr)
  424.     secptr->output_section = secptr;
  425.       seginfo = (segment_info_type *) xmalloc (sizeof (*seginfo));
  426.       memset ((PTR) seginfo, 0, sizeof (*seginfo));
  427.       seginfo->fix_root = NULL;
  428.       seginfo->fix_tail = NULL;
  429.       seginfo->bfd_section = secptr;
  430.       if (secptr == bfd_abs_section_ptr)
  431.     abs_seg_info = seginfo;
  432.       else if (secptr == bfd_und_section_ptr)
  433.     und_seg_info = seginfo;
  434.       else
  435.     bfd_set_section_userdata (stdoutput, secptr, (PTR) seginfo);
  436.       seginfo->frchainP = NULL;
  437.       seginfo->lineno_list_head = seginfo->lineno_list_tail = NULL;
  438.       seginfo->sym = NULL;
  439.       seginfo->dot = NULL;
  440.     }
  441.   return secptr;
  442. }
  443.  
  444. segT
  445. subseg_new (segname, subseg)
  446.      const char *segname;
  447.      subsegT subseg;
  448. {
  449.   segT secptr;
  450.   segment_info_type *seginfo;
  451.  
  452.   secptr = subseg_get (segname, 0);
  453.   subseg_set_rest (secptr, subseg);
  454.   seginfo = seg_info (secptr);
  455.   if (! seginfo->frchainP)
  456.     seginfo->frchainP = frchain_now;
  457.   return secptr;
  458. }
  459.  
  460. /* Like subseg_new, except a new section is always created, even if
  461.    a section with that name already exists.  */
  462. segT
  463. subseg_force_new (segname, subseg)
  464.      const char *segname;
  465.      subsegT subseg;
  466. {
  467.   segT secptr;
  468.   segment_info_type *seginfo;
  469.  
  470.   secptr = subseg_get (segname, 1);
  471.   subseg_set_rest (secptr, subseg);
  472.   seginfo = seg_info (secptr);
  473.   if (! seginfo->frchainP)
  474.     seginfo->frchainP = frchain_now;
  475.   return secptr;
  476. }
  477.  
  478. void
  479. subseg_set (secptr, subseg)
  480.      segT secptr;
  481.      subsegT subseg;
  482. {
  483.   if (! (secptr == now_seg && subseg == now_subseg))
  484.     subseg_set_rest (secptr, subseg);
  485.   mri_common_symbol = NULL;
  486. }
  487.  
  488. #ifndef obj_sec_sym_ok_for_reloc
  489. #define obj_sec_sym_ok_for_reloc(SEC)    0
  490. #endif
  491.  
  492. /* Get the gas information we are storing for a section.  */
  493.  
  494. segment_info_type *
  495. seg_info (sec)
  496.      segT sec;
  497. {
  498.   if (sec == bfd_abs_section_ptr)
  499.     return abs_seg_info;
  500.   else if (sec == bfd_und_section_ptr)
  501.     return und_seg_info;
  502.   else
  503.     return (segment_info_type *) bfd_get_section_userdata (stdoutput, sec);
  504. }
  505.  
  506. symbolS *
  507. section_symbol (sec)
  508.      segT sec;
  509. {
  510.   segment_info_type *seginfo = seg_info (sec);
  511.   symbolS *s;
  512.  
  513.   if (seginfo == 0)
  514.     abort ();
  515.   if (seginfo->sym)
  516.     return seginfo->sym;
  517.  
  518. #ifndef EMIT_SECTION_SYMBOLS
  519. #define EMIT_SECTION_SYMBOLS 1
  520. #endif
  521.  
  522.   if (! EMIT_SECTION_SYMBOLS
  523. #ifdef BFD_ASSEMBLER
  524.       || symbol_table_frozen
  525. #endif
  526.       )
  527.     /* Here we know it won't be going into the symbol table.  */
  528.     s = symbol_create (sec->name, sec, 0, &zero_address_frag);
  529.   else
  530.     s = symbol_new (sec->name, sec, 0, &zero_address_frag);
  531.   S_CLEAR_EXTERNAL (s);
  532.  
  533.   /* Use the BFD section symbol, if possible.  */
  534.   if (obj_sec_sym_ok_for_reloc (sec))
  535.     s->bsym = sec->symbol;
  536.  
  537.   seginfo->sym = s;
  538.   return s;
  539. }
  540.  
  541. #endif /* BFD_ASSEMBLER */
  542.  
  543. void
  544. subsegs_print_statistics (file)
  545.      FILE *file;
  546. {
  547.   frchainS *frchp;
  548.   fprintf (file, "frag chains:\n");
  549.   for (frchp = frchain_root; frchp; frchp = frchp->frch_next)
  550.     {
  551.       int count = 0;
  552.       fragS *fragp;
  553.  
  554.       /* If frch_subseg is non-zero, it's probably been chained onto
  555.      the end of a previous subsection.  Don't count it again.  */
  556.       if (frchp->frch_subseg != 0)
  557.     continue;
  558.  
  559.       /* Skip gas-internal sections.  */
  560.       if (segment_name (frchp->frch_seg)[0] == '*')
  561.     continue;
  562.  
  563.       for (fragp = frchp->frch_root; fragp; fragp = fragp->fr_next)
  564.     {
  565. #if 0
  566.       switch (fragp->fr_type)
  567.         {
  568.         case rs_fill:
  569.           fprintf (file, "f"); break;
  570.         case rs_align:
  571.           fprintf (file, "a"); break;
  572.         case rs_align_code:
  573.           fprintf (file, "c"); break;
  574.         case rs_org:
  575.           fprintf (file, "o"); break;
  576.         case rs_machine_dependent:
  577.           fprintf (file, "m"); break;
  578.         case rs_space:
  579.           fprintf (file, "s"); break;
  580.         case 0:
  581.           fprintf (file, "0"); break;
  582.         default:
  583.           fprintf (file, "?"); break;
  584.         }
  585. #endif
  586.       count++;
  587.     }
  588.       fprintf (file, "\n");
  589.       fprintf (file, "\t%p %-10s\t%10d frags\n", frchp,
  590.            segment_name (frchp->frch_seg), count);
  591.     }
  592. }
  593.  
  594. /* end of subsegs.c */
  595.