* som.c (struct som_misc_symbol_info): Add is_comdat, is_common and
[deliverable/binutils-gdb.git] / gas / subsegs.c
index 3280bcd18c070191450dd1eff5d6d8be4f7539cb..b2432e9a1f80c42178dfb09daeef9cb951ddfbff 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, 2002
    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"
 
@@ -36,15 +36,17 @@ static struct obstack frchains;
 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",
@@ -58,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
@@ -68,14 +70,14 @@ static segment_info_type *und_seg_info;
 
 #endif /* BFD_ASSEMBLER */
 
-static void subseg_set_rest PARAMS ((segT, subsegT));
+static void subseg_set_rest (segT, subsegT);
 
 static fragS dummy_frag;
 
 static frchainS absolute_frchain;
 \f
 void
-subsegs_begin ()
+subsegs_begin (void)
 {
   /* Check table(s) seg_name[], seg_N_TYPE[] is in correct order */
 #if !defined (MANY_SEGMENTS) && !defined (BFD_ASSEMBLER)
@@ -99,12 +101,12 @@ subsegs_begin ()
 #endif
 
   frchain_root = NULL;
-  frchain_now = NULL;          /* Warn new_subseg() that we are booting. */
+  frchain_now = NULL;          /* Warn new_subseg() that we are booting.  */
 
   frag_now = &dummy_frag;
 
 #ifndef BFD_ASSEMBLER
-  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;
@@ -126,7 +128,9 @@ subsegs_begin ()
 
   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;
 }
@@ -142,9 +146,7 @@ subsegs_begin ()
  * segment context correct.
  */
 void
-subseg_change (seg, subseg)
-     register segT seg;
-     register int subseg;
+subseg_change (register segT seg, register int subseg)
 {
   now_seg = seg;
   now_subseg = subseg;
@@ -199,16 +201,11 @@ subseg_change (seg, subseg)
 }
 \f
 static void
-subseg_set_rest (seg, subseg)
-     segT seg;
-     subsegT subseg;
+subseg_set_rest (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;
 
   mri_common_symbol = NULL;
 
@@ -272,12 +269,11 @@ 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.
        */
-      extern fragS *frag_alloc ();
       newP = (frchainS *) obstack_alloc (&frchains, sizeof (frchainS));
       newP->frch_subseg = subseg;
       newP->frch_seg = seg;
@@ -285,7 +281,7 @@ subseg_set_rest (seg, subseg)
       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
@@ -296,6 +292,16 @@ subseg_set_rest (seg, subseg)
 
       *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;
     }
   /*
@@ -364,7 +370,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
 }
@@ -391,9 +397,7 @@ subseg_set (seg, subseg)    /* begin assembly for a new sub-segment */
 #else /* BFD_ASSEMBLER */
 
 segT
-subseg_get (segname, force_new)
-     const char *segname;
-     int force_new;
+subseg_get (const char *segname, int force_new)
 {
   segT secptr;
   segment_info_type *seginfo;
@@ -412,11 +416,15 @@ subseg_get (segname, force_new)
   else
     secptr = bfd_make_section_anyway (stdoutput, segname);
 
+#ifdef obj_sec_set_private_data
+  obj_sec_set_private_data (stdoutput, secptr);
+#endif
+
   seginfo = seg_info (secptr);
   if (! seginfo)
     {
       /* Check whether output_section is set first because secptr may
-         be bfd_abs_section_ptr.  */
+        be bfd_abs_section_ptr.  */
       if (secptr->output_section != secptr)
        secptr->output_section = secptr;
       seginfo = (segment_info_type *) xmalloc (sizeof (*seginfo));
@@ -439,9 +447,7 @@ subseg_get (segname, force_new)
 }
 
 segT
-subseg_new (segname, subseg)
-     const char *segname;
-     subsegT subseg;
+subseg_new (const char *segname, subsegT subseg)
 {
   segT secptr;
   segment_info_type *seginfo;
@@ -457,9 +463,7 @@ subseg_new (segname, subseg)
 /* Like subseg_new, except a new section is always created, even if
    a section with that name already exists.  */
 segT
-subseg_force_new (segname, subseg)
-     const char *segname;
-     subsegT subseg;
+subseg_force_new (const char *segname, subsegT subseg)
 {
   segT secptr;
   segment_info_type *seginfo;
@@ -473,9 +477,7 @@ subseg_force_new (segname, subseg)
 }
 
 void
-subseg_set (secptr, subseg)
-     segT secptr;
-     subsegT subseg;
+subseg_set (segT secptr, subsegT subseg)
 {
   if (! (secptr == now_seg && subseg == now_subseg))
     subseg_set_rest (secptr, subseg);
@@ -489,8 +491,7 @@ subseg_set (secptr, subseg)
 /* Get the gas information we are storing for a section.  */
 
 segment_info_type *
-seg_info (sec)
-     segT sec;
+seg_info (segT sec)
 {
   if (sec == bfd_abs_section_ptr)
     return abs_seg_info;
@@ -501,8 +502,7 @@ seg_info (sec)
 }
 
 symbolS *
-section_symbol (sec)
-     segT sec;
+section_symbol (segT sec)
 {
   segment_info_type *seginfo = seg_info (sec);
   symbolS *s;
@@ -511,32 +511,136 @@ 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
-#ifdef BFD_ASSEMBLER
-         && 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);
+  if (! EMIT_SECTION_SYMBOLS || symbol_table_frozen)
+    {
+      /* Here we know it won't be going into the symbol table.  */
+      s = symbol_create (sec->symbol->name, sec, 0, &zero_address_frag);
+    }
+  else
+    {
+      s = symbol_find_base (sec->symbol->name, 0);
+      if (s == NULL)
+       s = symbol_new (sec->symbol->name, sec, 0, &zero_address_frag);
       else
-       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;
+       {
+         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);
+  else
+    symbol_get_bfdsym (s)->flags |= BSF_SECTION_SYM;
+
   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 (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 || sec == absolute_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)
+{
+  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", (void *) frchp,
+              segment_name (frchp->frch_seg), count);
+    }
+}
+
 /* end of subsegs.c */
This page took 0.028632 seconds and 4 git commands to generate.