X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fsubsegs.c;h=c8159531ef3355c11a62aff4b7b605e7f8689b35;hb=3765b1be13d34da8aae366959c3601a09afa193b;hp=55e111e9819a6b5ca6e00241064d6fde201167dc;hpb=dff770c8d62a4e900c509ab23ea0bba0a1f11de0;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/subsegs.c b/gas/subsegs.c index 55e111e981..c8159531ef 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, 675 Mass Ave, Cambridge, MA 02139, 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 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 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,18 +95,18 @@ subsegs_begin () know (SEG_MAXIMUM_ORDINAL == SEG_REGISTER); #endif - obstack_begin (&frags, 5000); + 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; @@ -118,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; } /* @@ -138,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; @@ -145,8 +163,7 @@ subseg_change (seg, subseg) if (! seginfo) { seginfo = (segment_info_type *) xmalloc (sizeof (*seginfo)); - if (! seginfo) - abort (); + memset ((PTR) seginfo, 0, sizeof (*seginfo)); seginfo->fix_root = NULL; seginfo->fix_tail = NULL; seginfo->bfd_section = seg; @@ -190,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 = (char*) obstack_next_free (&frags) - frag_now->fr_literal; - 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. @@ -224,10 +241,10 @@ subseg_set_rest (seg, subseg) * position of chain rooted in frchain_root. */ for (frcP = *(lastPP = &frchain_root); - frcP && (int) (frcP->frch_seg) <= (int) seg; + frcP && frcP->frch_seg <= seg; frcP = *(lastPP = &frcP->frch_next)) { - if ((int) (frcP->frch_seg) == (int) seg + if (frcP->frch_seg == seg && frcP->frch_subseg >= subseg) { break; @@ -255,60 +272,49 @@ subseg_set_rest (seg, subseg) * */ if (!frcP - || ((int) (frcP->frch_seg) > (int) seg - || frcP->frch_subseg > subseg)) /* Kinky logic only works with 2 segments. */ + || (frcP->frch_seg > seg + || 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)); - memset (newP, 0, sizeof (frchainS)); - /* This begines on a good boundary because a obstack_done() - preceeded it. It implies an obstack_done(), so we expect - the next object allocated to begin on a correct boundary. */ - *lastPP = newP; - newP->frch_next = frcP; /* perhaps NULL */ - (frcP = newP)->frch_subseg = subseg; + 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, 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 ->ing to the frchainS for subseg. + * 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; + + 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,13 +385,17 @@ 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) { /* we just changed sub-segments */ subseg_set_rest (seg, subseg); } + mri_common_symbol = NULL; } #else /* BFD_ASSEMBLER */ @@ -420,7 +430,7 @@ subseg_get (segname, force_new) if (secptr->output_section != secptr) secptr->output_section = secptr; seginfo = (segment_info_type *) xmalloc (sizeof (*seginfo)); - memset ((char *) seginfo, 0, sizeof(seginfo)); + memset ((PTR) seginfo, 0, sizeof (*seginfo)); seginfo->fix_root = NULL; seginfo->fix_tail = NULL; seginfo->bfd_section = secptr; @@ -479,6 +489,7 @@ subseg_set (secptr, subseg) { if (! (secptr == now_seg && subseg == now_subseg)) subseg_set_rest (secptr, subseg); + mri_common_symbol = NULL; } #ifndef obj_sec_sym_ok_for_reloc @@ -510,20 +521,140 @@ section_symbol (sec) abort (); if (seginfo->sym) return seginfo->sym; - s = symbol_find (sec->name); - if (!s) - { - 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; +#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); + } + else + { + s = symbol_find_base (sec->name, 0); + if (s == NULL) + s = symbol_new (sec->name, sec, 0, &zero_address_frag); + 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 || 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 *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 */