133965Sjdp/* subsegs.c - subsegments - 278828Sobrien Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 3218822Sdim 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 433965Sjdp Free Software Foundation, Inc. 533965Sjdp 633965Sjdp This file is part of GAS, the GNU Assembler. 733965Sjdp 833965Sjdp GAS is free software; you can redistribute it and/or modify 933965Sjdp it under the terms of the GNU General Public License as published by 1033965Sjdp the Free Software Foundation; either version 2, or (at your option) 1133965Sjdp any later version. 1233965Sjdp 1333965Sjdp GAS is distributed in the hope that it will be useful, 1433965Sjdp but WITHOUT ANY WARRANTY; without even the implied warranty of 1533965Sjdp MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1633965Sjdp GNU General Public License for more details. 1733965Sjdp 1833965Sjdp You should have received a copy of the GNU General Public License 1933965Sjdp along with GAS; see the file COPYING. If not, write to the Free 20218822Sdim Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 21218822Sdim 02110-1301, USA. */ 2233965Sjdp 2377298Sobrien/* Segments & sub-segments. */ 2433965Sjdp 2533965Sjdp#include "as.h" 2633965Sjdp 2733965Sjdp#include "subsegs.h" 2833965Sjdp#include "obstack.h" 2933965Sjdp 30218822SdimfrchainS *frchain_now; 3133965Sjdp 3233965Sjdpstatic struct obstack frchains; 3333965Sjdp 3433965Sjdpstatic fragS dummy_frag; 3533965Sjdp 3633965Sjdp 3733965Sjdpvoid 38130561Sobriensubsegs_begin (void) 3933965Sjdp{ 4033965Sjdp obstack_begin (&frchains, chunksize); 4133965Sjdp#if __GNUC__ >= 2 4233965Sjdp obstack_alignment_mask (&frchains) = __alignof__ (frchainS) - 1; 4333965Sjdp#endif 4433965Sjdp 4577298Sobrien frchain_now = NULL; /* Warn new_subseg() that we are booting. */ 4633965Sjdp frag_now = &dummy_frag; 4733965Sjdp} 4833965Sjdp 4933965Sjdp/* 5033965Sjdp * subseg_change() 5133965Sjdp * 5233965Sjdp * Change the subsegment we are in, BUT DO NOT MAKE A NEW FRAG for the 5333965Sjdp * subsegment. If we are already in the correct subsegment, change nothing. 5433965Sjdp * This is used eg as a worker for subseg_set [which does make a new frag_now] 5533965Sjdp * and for changing segments after we have read the source. We construct eg 5633965Sjdp * fixSs even after the source file is read, so we do have to keep the 5733965Sjdp * segment context correct. 5833965Sjdp */ 5933965Sjdpvoid 60130561Sobriensubseg_change (register segT seg, register int subseg) 6133965Sjdp{ 62218822Sdim segment_info_type *seginfo = seg_info (seg); 6333965Sjdp now_seg = seg; 6433965Sjdp now_subseg = subseg; 6533965Sjdp 66218822Sdim if (! seginfo) 6733965Sjdp { 68218822Sdim seginfo = xcalloc (1, sizeof (*seginfo)); 69218822Sdim seginfo->bfd_section = seg; 70223262Sbenl (void) bfd_set_section_userdata (stdoutput, seg, seginfo); 7133965Sjdp } 7233965Sjdp} 7333965Sjdp 7433965Sjdpstatic void 75130561Sobriensubseg_set_rest (segT seg, subsegT subseg) 7633965Sjdp{ 77218822Sdim frchainS *frcP; /* crawl frchain chain */ 78218822Sdim frchainS **lastPP; /* address of last pointer */ 7933965Sjdp frchainS *newP; /* address of new frchain */ 80218822Sdim segment_info_type *seginfo; 8133965Sjdp 8233965Sjdp mri_common_symbol = NULL; 8333965Sjdp 8433965Sjdp if (frag_now && frchain_now) 8533965Sjdp frchain_now->frch_frag_now = frag_now; 8633965Sjdp 8733965Sjdp assert (frchain_now == 0 8833965Sjdp || frchain_now->frch_last == frag_now); 8933965Sjdp 9033965Sjdp subseg_change (seg, (int) subseg); 9133965Sjdp 92218822Sdim seginfo = seg_info (seg); 9333965Sjdp 94218822Sdim /* Attempt to find or make a frchain for that subsection. 95218822Sdim We keep the list sorted by subsection number. */ 96218822Sdim for (frcP = *(lastPP = &seginfo->frchainP); 97218822Sdim frcP != NULL; 98218822Sdim frcP = *(lastPP = &frcP->frch_next)) 99218822Sdim if (frcP->frch_subseg >= subseg) 100218822Sdim break; 10133965Sjdp 102218822Sdim if (frcP == NULL || frcP->frch_subseg != subseg) 10333965Sjdp { 104218822Sdim /* This should be the only code that creates a frchainS. */ 105218822Sdim 106218822Sdim newP = obstack_alloc (&frchains, sizeof (frchainS)); 10733965Sjdp newP->frch_subseg = subseg; 10833965Sjdp newP->fix_root = NULL; 10933965Sjdp newP->fix_tail = NULL; 11038889Sjdp obstack_begin (&newP->frch_obstack, chunksize); 11133965Sjdp#if __GNUC__ >= 2 11233965Sjdp obstack_alignment_mask (&newP->frch_obstack) = __alignof__ (fragS) - 1; 11333965Sjdp#endif 11433965Sjdp newP->frch_frag_now = frag_alloc (&newP->frch_obstack); 11533965Sjdp newP->frch_frag_now->fr_type = rs_fill; 116218822Sdim newP->frch_cfi_data = NULL; 11733965Sjdp 11833965Sjdp newP->frch_root = newP->frch_last = newP->frch_frag_now; 11933965Sjdp 12033965Sjdp *lastPP = newP; 121218822Sdim newP->frch_next = frcP; 12233965Sjdp frcP = newP; 12333965Sjdp } 124218822Sdim 12533965Sjdp frchain_now = frcP; 12633965Sjdp frag_now = frcP->frch_frag_now; 12733965Sjdp 12833965Sjdp assert (frchain_now->frch_last == frag_now); 12933965Sjdp} 13033965Sjdp 13133965Sjdp/* 13233965Sjdp * subseg_set(segT, subsegT) 13333965Sjdp * 13433965Sjdp * If you attempt to change to the current subsegment, nothing happens. 13533965Sjdp * 13633965Sjdp * In: segT, subsegT code for new subsegment. 13733965Sjdp * frag_now -> incomplete frag for current subsegment. 13833965Sjdp * If frag_now==NULL, then there is no old, incomplete frag, so 13933965Sjdp * the old frag is not closed off. 14033965Sjdp * 14133965Sjdp * Out: now_subseg, now_seg updated. 14233965Sjdp * Frchain_now points to the (possibly new) struct frchain for this 14333965Sjdp * sub-segment. 14433965Sjdp */ 14533965Sjdp 14633965SjdpsegT 147130561Sobriensubseg_get (const char *segname, int force_new) 14833965Sjdp{ 14933965Sjdp segT secptr; 15033965Sjdp segment_info_type *seginfo; 15133965Sjdp const char *now_seg_name = (now_seg 15233965Sjdp ? bfd_get_section_name (stdoutput, now_seg) 15333965Sjdp : 0); 15433965Sjdp 15533965Sjdp if (!force_new 15633965Sjdp && now_seg_name 15733965Sjdp && (now_seg_name == segname 15833965Sjdp || !strcmp (now_seg_name, segname))) 15933965Sjdp return now_seg; 16033965Sjdp 16133965Sjdp if (!force_new) 16233965Sjdp secptr = bfd_make_section_old_way (stdoutput, segname); 16333965Sjdp else 16433965Sjdp secptr = bfd_make_section_anyway (stdoutput, segname); 16533965Sjdp 16633965Sjdp seginfo = seg_info (secptr); 16733965Sjdp if (! seginfo) 16833965Sjdp { 169218822Sdim secptr->output_section = secptr; 170218822Sdim seginfo = xcalloc (1, sizeof (*seginfo)); 17133965Sjdp seginfo->bfd_section = secptr; 172223262Sbenl (void) bfd_set_section_userdata (stdoutput, secptr, seginfo); 17333965Sjdp } 17433965Sjdp return secptr; 17533965Sjdp} 17633965Sjdp 17733965SjdpsegT 178130561Sobriensubseg_new (const char *segname, subsegT subseg) 17933965Sjdp{ 18033965Sjdp segT secptr; 18133965Sjdp 18233965Sjdp secptr = subseg_get (segname, 0); 18333965Sjdp subseg_set_rest (secptr, subseg); 18433965Sjdp return secptr; 18533965Sjdp} 18633965Sjdp 18733965Sjdp/* Like subseg_new, except a new section is always created, even if 18833965Sjdp a section with that name already exists. */ 18933965SjdpsegT 190130561Sobriensubseg_force_new (const char *segname, subsegT subseg) 19133965Sjdp{ 19233965Sjdp segT secptr; 19333965Sjdp 19433965Sjdp secptr = subseg_get (segname, 1); 19533965Sjdp subseg_set_rest (secptr, subseg); 19633965Sjdp return secptr; 19733965Sjdp} 19833965Sjdp 19933965Sjdpvoid 200130561Sobriensubseg_set (segT secptr, subsegT subseg) 20133965Sjdp{ 20233965Sjdp if (! (secptr == now_seg && subseg == now_subseg)) 20333965Sjdp subseg_set_rest (secptr, subseg); 20433965Sjdp mri_common_symbol = NULL; 20533965Sjdp} 20633965Sjdp 20733965Sjdp#ifndef obj_sec_sym_ok_for_reloc 20833965Sjdp#define obj_sec_sym_ok_for_reloc(SEC) 0 20933965Sjdp#endif 21033965Sjdp 21133965SjdpsymbolS * 212130561Sobriensection_symbol (segT sec) 21333965Sjdp{ 21433965Sjdp segment_info_type *seginfo = seg_info (sec); 21533965Sjdp symbolS *s; 21633965Sjdp 21733965Sjdp if (seginfo == 0) 21833965Sjdp abort (); 21933965Sjdp if (seginfo->sym) 22033965Sjdp return seginfo->sym; 22133965Sjdp 22233965Sjdp#ifndef EMIT_SECTION_SYMBOLS 22333965Sjdp#define EMIT_SECTION_SYMBOLS 1 22433965Sjdp#endif 22533965Sjdp 226130561Sobrien if (! EMIT_SECTION_SYMBOLS || symbol_table_frozen) 22760484Sobrien { 22860484Sobrien /* Here we know it won't be going into the symbol table. */ 229130561Sobrien s = symbol_create (sec->symbol->name, sec, 0, &zero_address_frag); 23060484Sobrien } 23133965Sjdp else 23260484Sobrien { 233218822Sdim segT seg; 234218822Sdim s = symbol_find (sec->symbol->name); 235218822Sdim /* We have to make sure it is the right symbol when we 236218822Sdim have multiple sections with the same section name. */ 237218822Sdim if (s == NULL 238218822Sdim || ((seg = S_GET_SEGMENT (s)) != sec 239218822Sdim && seg != undefined_section)) 240130561Sobrien s = symbol_new (sec->symbol->name, sec, 0, &zero_address_frag); 241218822Sdim else if (seg == undefined_section) 24260484Sobrien { 243218822Sdim S_SET_SEGMENT (s, sec); 244218822Sdim symbol_set_frag (s, &zero_address_frag); 24560484Sobrien } 24660484Sobrien } 24760484Sobrien 24833965Sjdp S_CLEAR_EXTERNAL (s); 24933965Sjdp 25033965Sjdp /* Use the BFD section symbol, if possible. */ 25133965Sjdp if (obj_sec_sym_ok_for_reloc (sec)) 25260484Sobrien symbol_set_bfdsym (s, sec->symbol); 253130561Sobrien else 254130561Sobrien symbol_get_bfdsym (s)->flags |= BSF_SECTION_SYM; 25533965Sjdp 25633965Sjdp seginfo->sym = s; 25733965Sjdp return s; 25833965Sjdp} 25933965Sjdp 26060484Sobrien/* Return whether the specified segment is thought to hold text. */ 26160484Sobrien 26260484Sobrienint 263130561Sobriensubseg_text_p (segT sec) 26460484Sobrien{ 26560484Sobrien return (bfd_get_section_flags (stdoutput, sec) & SEC_CODE) != 0; 266218822Sdim} 26760484Sobrien 268218822Sdim/* Return non zero if SEC has at least one byte of data. It is 269218822Sdim possible that we'll return zero even on a non-empty section because 270218822Sdim we don't know all the fragment types, and it is possible that an 271218822Sdim fr_fix == 0 one still contributes data. Think of this as 272218822Sdim seg_definitely_not_empty_p. */ 273218822Sdim 274218822Sdimint 275218822Sdimseg_not_empty_p (segT sec ATTRIBUTE_UNUSED) 276218822Sdim{ 277218822Sdim segment_info_type *seginfo = seg_info (sec); 278218822Sdim frchainS *chain; 279218822Sdim fragS *frag; 280218822Sdim 281218822Sdim if (!seginfo) 28260484Sobrien return 0; 283218822Sdim 284218822Sdim for (chain = seginfo->frchainP; chain; chain = chain->frch_next) 28560484Sobrien { 286218822Sdim for (frag = chain->frch_root; frag; frag = frag->fr_next) 287218822Sdim if (frag->fr_fix) 288218822Sdim return 1; 289218822Sdim if (obstack_next_free (&chain->frch_obstack) 290218822Sdim != chain->frch_last->fr_literal) 291218822Sdim return 1; 29260484Sobrien } 293218822Sdim return 0; 29460484Sobrien} 29560484Sobrien 29633965Sjdpvoid 297130561Sobriensubsegs_print_statistics (FILE *file) 29833965Sjdp{ 29933965Sjdp frchainS *frchp; 300218822Sdim asection *s; 301218822Sdim 30233965Sjdp fprintf (file, "frag chains:\n"); 303218822Sdim for (s = stdoutput->sections; s; s = s->next) 30433965Sjdp { 305218822Sdim segment_info_type *seginfo; 30633965Sjdp 307218822Sdim /* Skip gas-internal sections. */ 308218822Sdim if (segment_name (s)[0] == '*') 30933965Sjdp continue; 31033965Sjdp 311218822Sdim seginfo = seg_info (s); 312218822Sdim if (!seginfo) 31333965Sjdp continue; 31433965Sjdp 315218822Sdim for (frchp = seginfo->frchainP; frchp; frchp = frchp->frch_next) 31633965Sjdp { 317218822Sdim int count = 0; 318218822Sdim fragS *fragp; 319218822Sdim 320218822Sdim for (fragp = frchp->frch_root; fragp; fragp = fragp->fr_next) 321218822Sdim count++; 322218822Sdim 323218822Sdim fprintf (file, "\n"); 324218822Sdim fprintf (file, "\t%p %-10s\t%10d frags\n", (void *) frchp, 325218822Sdim segment_name (s), count); 32633965Sjdp } 32733965Sjdp } 32833965Sjdp} 32933965Sjdp 33033965Sjdp/* end of subsegs.c */ 331