* read.c: Standardize error/warning messages - don't capitalise, no
[deliverable/binutils-gdb.git] / gas / subsegs.c
index e360d3294870217ad8e948f8694d4091c56d1d4c..f5a1022fdf526d4af7a46fb02076029e5465487b 100644 (file)
@@ -1,5 +1,6 @@
 /* subsegs.c - subsegments -
-   Copyright (C) 1987, 1990, 1991, 1992, 1993, 1994
+   Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+   1999, 2000
    Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with GAS; see the file COPYING.  If not, write to
-   the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   along with GAS; see the file COPYING.  If not, write to the Free
+   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
 
-/*
- * Segments & sub-segments.
- */
+/* Segments & sub-segments.  */
 
 #include "as.h"
 
 
 frchainS *frchain_root, *frchain_now;
 
+static struct obstack frchains;
+
 #ifndef BFD_ASSEMBLER
 #ifdef MANY_SEGMENTS
 segment_info_type segment_info[SEG_MAXIMUM_ORDINAL];
 
 #else
-/* Commented in "subsegs.h". */
+/* Commented in "subsegs.h".  */
 frchainS *data0_frchainP, *bss0_frchainP;
 
 #endif /* MANY_SEGMENTS */
-char const *const seg_name[] =
-{
+char const *const seg_name[] = {
   "absolute",
 #ifdef MANY_SEGMENTS
   "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9",
+  "e10", "e11", "e12", "e13", "e14", "e15", "e16", "e17", "e18", "e19",
+  "e20", "e21", "e22", "e23", "e24", "e25", "e26", "e27", "e28", "e29",
+  "e30", "e31", "e32", "e33", "e34", "e35", "e36", "e37", "e38", "e39",
 #else
   "text",
   "data",
@@ -56,7 +60,7 @@ char const *const seg_name[] =
   "transfert vector postload",
   "register",
   "",
-};                             /* Used by error reporters, dumpers etc. */
+};                             /* Used by error reporters, dumpers etc.  */
 #else /* BFD_ASSEMBLER */
 
 /* Gas segment information for bfd_abs_section_ptr and
@@ -67,6 +71,10 @@ static segment_info_type *und_seg_info;
 #endif /* BFD_ASSEMBLER */
 
 static void subseg_set_rest PARAMS ((segT, subsegT));
+
+static fragS dummy_frag;
+
+static frchainS absolute_frchain;
 \f
 void
 subsegs_begin ()
@@ -87,17 +95,18 @@ subsegs_begin ()
   know (SEG_MAXIMUM_ORDINAL == SEG_REGISTER);
 #endif
 
+  obstack_begin (&frchains, chunksize);
+#if __GNUC__ >= 2
+  obstack_alignment_mask (&frchains) = __alignof__ (frchainS) - 1;
+#endif
+
   frchain_root = NULL;
-  frchain_now = NULL;          /* Warn new_subseg() that we are booting. */
-  /* Fake up 1st frag.  It won't be used=> is ok if obstack...
-     pads the end of it for alignment. */
-  frag_now = (fragS *) obstack_alloc (&frags, SIZEOF_STRUCT_FRAG);
-  memset (frag_now, 0, SIZEOF_STRUCT_FRAG);
+  frchain_now = NULL;          /* Warn new_subseg() that we are booting.  */
+
+  frag_now = &dummy_frag;
 
 #ifndef BFD_ASSEMBLER
-  /* This 1st frag will not be in any frchain.
-     We simply give subseg_new somewhere to scribble. */
-  now_subseg = 42;             /* Lie for 1st call to subseg_new. */
+  now_subseg = 42;             /* Lie for 1st call to subseg_new.  */
 #ifdef MANY_SEGMENTS
   {
     int i;
@@ -117,6 +126,13 @@ subsegs_begin ()
 #endif /* ! MANY_SEGMENTS */
 #endif /* ! BFD_ASSEMBLER */
 
+  absolute_frchain.frch_seg = absolute_section;
+  absolute_frchain.frch_subseg = 0;
+#ifdef BFD_ASSEMBLER
+  absolute_frchain.fix_root = absolute_frchain.fix_tail = 0;
+#endif
+  absolute_frchain.frch_frag_now = &zero_address_frag;
+  absolute_frchain.frch_root = absolute_frchain.frch_last = &zero_address_frag;
 }
 \f
 /*
@@ -137,6 +153,9 @@ subseg_change (seg, subseg)
   now_seg = seg;
   now_subseg = subseg;
 
+  if (now_seg == absolute_section)
+    return;
+
 #ifdef BFD_ASSEMBLER
   {
     segment_info_type *seginfo;
@@ -188,33 +207,33 @@ subseg_set_rest (seg, subseg)
      segT seg;
      subsegT subseg;
 {
-  long tmp;                    /* JF for obstack alignment hacking */
   register frchainS *frcP;     /* crawl frchain chain */
   register frchainS **lastPP;  /* address of last pointer */
   frchainS *newP;              /* address of new frchain */
-  register fragS *former_last_fragP;
-  register fragS *new_fragP;
 
-  if (frag_now)                /* If not bootstrapping. */
+  mri_common_symbol = NULL;
+
+  if (frag_now && frchain_now)
+    frchain_now->frch_frag_now = frag_now;
+
+  assert (frchain_now == 0
+         || now_seg == undefined_section
+         || now_seg == absolute_section
+         || frchain_now->frch_last == frag_now);
+
+  subseg_change (seg, (int) subseg);
+
+  if (seg == absolute_section)
     {
-      frag_now->fr_fix = frag_now_fix ();
-      frag_wane (frag_now);    /* Close off any frag in old subseg. */
+      frchain_now = &absolute_frchain;
+      frag_now = &zero_address_frag;
+      return;
     }
-  /*
-   * It would be nice to keep an obstack for each subsegment, if we swap
-   * subsegments a lot. Hence we would have much fewer frag_wanes().
-   */
-  {
-    obstack_finish (&frags);
-    /*
-     * If we don't do the above, the next object we put on obstack frags
-     * will appear to start at the fr_literal of the current frag.
-     * Also, above ensures that the next object will begin on a
-     * address that is aligned correctly for the engine that runs
-     * this program.
-     */
-  }
-  subseg_change (seg, (int) subseg);
+
+  assert (frchain_now == 0
+         || now_seg == undefined_section
+         || frchain_now->frch_last == frag_now);
+
   /*
    * Attempt to find or make a frchain for that sub seg.
    * Crawl along chain of frchainSs, begins @ frchain_root.
@@ -254,61 +273,48 @@ subseg_set_rest (seg, subseg)
    */
   if (!frcP
       || (frcP->frch_seg > seg
-         || frcP->frch_subseg > subseg))       /* Kinky logic only works with 2 segments. */
+         || frcP->frch_subseg > subseg))       /* Kinky logic only works with 2 segments.  */
     {
       /*
        * This should be the only code that creates a frchainS.
        */
-      newP = (frchainS *) obstack_alloc (&frags, sizeof (frchainS));
-      newP->frch_root = 0;
+      newP = (frchainS *) obstack_alloc (&frchains, sizeof (frchainS));
       newP->frch_subseg = subseg;
       newP->frch_seg = seg;
-      newP->frch_last = NULL;
 #ifdef BFD_ASSEMBLER
       newP->fix_root = NULL;
       newP->fix_tail = NULL;
 #endif
-      obstack_begin (&newP->frch_obstack, 5000);
+      obstack_begin (&newP->frch_obstack, chunksize);
+#if __GNUC__ >= 2
+      obstack_alignment_mask (&newP->frch_obstack) = __alignof__ (fragS) - 1;
+#endif
+      newP->frch_frag_now = frag_alloc (&newP->frch_obstack);
+      newP->frch_frag_now->fr_type = rs_fill;
+
+      newP->frch_root = newP->frch_last = newP->frch_frag_now;
 
       *lastPP = newP;
       newP->frch_next = frcP;  /* perhaps NULL */
+
+#ifdef BFD_ASSEMBLER
+      {
+       segment_info_type *seginfo;
+       seginfo = seg_info (seg);
+       if (seginfo && seginfo->frchainP == frcP)
+         seginfo->frchainP = newP;
+      }
+#endif
+
       frcP = newP;
     }
   /*
    * Here with frcP pointing to the frchainS for subseg.
    */
   frchain_now = frcP;
-  /*
-   * Make a fresh frag for the subsegment.
-   */
-  /* We expect this to happen on a correct boundary since it was
-     proceeded by a obstack_done(). */
-  tmp = obstack_alignment_mask (&frags);       /* JF disable alignment */
-  obstack_alignment_mask (&frags) = 0;
-  frag_now = (fragS *) obstack_alloc (&frags, SIZEOF_STRUCT_FRAG);
-  memset (frag_now, 0, SIZEOF_STRUCT_FRAG);
-  obstack_alignment_mask (&frags) = tmp;
-  /* But we want any more chars to come immediately after the
-     structure we just made. */
-  new_fragP = frag_now;
-  new_fragP->fr_next = NULL;
-  /*
-   * Append new frag to current frchain.
-   */
-  former_last_fragP = frcP->frch_last;
-  if (former_last_fragP)
-    {
-      know (former_last_fragP->fr_next == NULL);
-      know (frchain_now->frch_root);
-      former_last_fragP->fr_next = new_fragP;
-    }
-  else
-    {
-      frcP->frch_root = new_fragP;
-    }
-  frcP->frch_last = new_fragP;
+  frag_now = frcP->frch_frag_now;
 
-  mri_common_symbol = NULL;
+  assert (frchain_now->frch_last == frag_now);
 }
 
 /*
@@ -368,7 +374,7 @@ subseg_new (segname, subseg)
     return new_seg;
   }
 #else
-  as_bad ("Attempt to switch to nonexistent segment \"%s\"", segname);
+  as_bad (_("attempt to switch to nonexistent segment \"%s\""), segname);
   return now_seg;
 #endif
 }
@@ -379,7 +385,10 @@ subseg_set (seg, subseg)   /* begin assembly for a new sub-segment */
      register subsegT subseg;
 {
 #ifndef MANY_SEGMENTS
-  know (seg == SEG_DATA || seg == SEG_TEXT || seg == SEG_BSS);
+  know (seg == SEG_DATA
+       || seg == SEG_TEXT
+       || seg == SEG_BSS
+       || seg == SEG_ABSOLUTE);
 #endif
 
   if (seg != now_seg || subseg != now_subseg)
@@ -512,32 +521,140 @@ section_symbol (sec)
     abort ();
   if (seginfo->sym)
     return seginfo->sym;
-  s = symbol_find (sec->name);
-  if (!s)
-    {
+
 #ifndef EMIT_SECTION_SYMBOLS
 #define EMIT_SECTION_SYMBOLS 1
 #endif
 
-      if (! EMIT_SECTION_SYMBOLS
+  if (! EMIT_SECTION_SYMBOLS
 #ifdef BFD_ASSEMBLER
-         && symbol_table_frozen
+      || symbol_table_frozen
 #endif
-         )
-       /* Here we know it won't be going into the symbol table.  */
-       s = symbol_create (sec->name, sec, 0, &zero_address_frag);
-      else
+      )
+    {
+      /* Here we know it won't be going into the symbol table.  */
+      s = symbol_create (sec->name, sec, 0, &zero_address_frag);
+    }
+  else
+    {
+      s = symbol_find_base (sec->name, 0);
+      if (s == NULL)
        s = symbol_new (sec->name, sec, 0, &zero_address_frag);
-      S_CLEAR_EXTERNAL (s);
-
-      /* Use the BFD section symbol, if possible.  */
-      if (obj_sec_sym_ok_for_reloc (sec))
-       s->bsym = sec->symbol;
+      else
+       {
+         if (S_GET_SEGMENT (s) == undefined_section)
+           {
+             S_SET_SEGMENT (s, sec);
+             symbol_set_frag (s, &zero_address_frag);
+           }
+       }
     }
+
+  S_CLEAR_EXTERNAL (s);
+
+  /* Use the BFD section symbol, if possible.  */
+  if (obj_sec_sym_ok_for_reloc (sec))
+    symbol_set_bfdsym (s, sec->symbol);
+
   seginfo->sym = s;
   return s;
 }
 
 #endif /* BFD_ASSEMBLER */
 
+/* Return whether the specified segment is thought to hold text.  */
+
+#ifndef BFD_ASSEMBLER
+const char * const nontext_section_names[] = {
+  ".eh_frame",
+  ".gcc_except_table",
+#ifdef OBJ_COFF
+#ifndef COFF_LONG_SECTION_NAMES
+  ".eh_fram",
+  ".gcc_exc",
+#endif
+#endif
+  NULL
+};
+#endif /* ! BFD_ASSEMBLER */
+
+int
+subseg_text_p (sec)
+     segT sec;
+{
+#ifdef BFD_ASSEMBLER
+  return (bfd_get_section_flags (stdoutput, sec) & SEC_CODE) != 0;
+#else /* ! BFD_ASSEMBLER */
+  const char * const *p;
+
+  if (sec == data_section || sec == bss_section)
+    return 0;
+
+  for (p = nontext_section_names; *p != NULL; ++p)
+    {
+      if (strcmp (segment_name (sec), *p) == 0)
+       return 0;
+
+#ifdef obj_segment_name
+      if (strcmp (obj_segment_name (sec), *p) == 0)
+       return 0;
+#endif
+    }
+
+  return 1;
+
+#endif /* ! BFD_ASSEMBLER */
+}
+
+void
+subsegs_print_statistics (file)
+     FILE *file;
+{
+  frchainS *frchp;
+  fprintf (file, "frag chains:\n");
+  for (frchp = frchain_root; frchp; frchp = frchp->frch_next)
+    {
+      int count = 0;
+      fragS *fragp;
+
+      /* If frch_subseg is non-zero, it's probably been chained onto
+        the end of a previous subsection.  Don't count it again.  */
+      if (frchp->frch_subseg != 0)
+       continue;
+
+      /* Skip gas-internal sections.  */
+      if (segment_name (frchp->frch_seg)[0] == '*')
+       continue;
+
+      for (fragp = frchp->frch_root; fragp; fragp = fragp->fr_next)
+       {
+#if 0
+         switch (fragp->fr_type)
+           {
+           case rs_fill:
+             fprintf (file, "f"); break;
+           case rs_align:
+             fprintf (file, "a"); break;
+           case rs_align_code:
+             fprintf (file, "c"); break;
+           case rs_org:
+             fprintf (file, "o"); break;
+           case rs_machine_dependent:
+             fprintf (file, "m"); break;
+           case rs_space:
+             fprintf (file, "s"); break;
+           case 0:
+             fprintf (file, "0"); break;
+           default:
+             fprintf (file, "?"); break;
+           }
+#endif
+         count++;
+       }
+      fprintf (file, "\n");
+      fprintf (file, "\t%p %-10s\t%10d frags\n", frchp,
+              segment_name (frchp->frch_seg), count);
+    }
+}
+
 /* end of subsegs.c */
This page took 0.028836 seconds and 4 git commands to generate.