/* subsegs.c - subsegments -
- Copyright (C) 1987, 1990, 1991, 1992, 1993, 1994
+ Copyright (C) 1987, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 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"
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",
"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
#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;
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;
}
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;
*/
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;
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
*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;
}
/*
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
}
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 */