X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gas%2Fsubsegs.c;h=f5a1022fdf526d4af7a46fb02076029e5465487b;hb=0e389e770d54185d8107db1972d3ae0576d0fa1d;hp=e360d3294870217ad8e948f8694d4091c56d1d4c;hpb=1356d77df3d5860b008035d6ad2f4f1f7093b0fe;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/subsegs.c b/gas/subsegs.c index e360d32948..f5a1022fdf 100644 --- a/gas/subsegs.c +++ b/gas/subsegs.c @@ -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. @@ -15,12 +16,11 @@ 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" @@ -29,20 +29,24 @@ 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; 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; } /* @@ -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 */