1/* subsegs.c - subsegments - 2 Copyright (C) 1987-2022 Free Software Foundation, Inc. 3 4 This file is part of GAS, the GNU Assembler. 5 6 GAS is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3, or (at your option) 9 any later version. 10 11 GAS is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GAS; see the file COPYING. If not, write to the Free 18 Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 19 02110-1301, USA. */ 20 21/* Segments & sub-segments. */ 22 23#include "as.h" 24 25#include "subsegs.h" 26#include "obstack.h" 27 28frchainS *frchain_now; 29 30static struct obstack frchains; 31 32static fragS dummy_frag; 33 34 35void 36subsegs_begin (void) 37{ 38 obstack_begin (&frchains, chunksize); 39#if __GNUC__ >= 2 40 obstack_alignment_mask (&frchains) = __alignof__ (frchainS) - 1; 41#endif 42 43 frchain_now = NULL; /* Warn new_subseg() that we are booting. */ 44 frag_now = &dummy_frag; 45} 46 47void 48subsegs_end (struct obstack **obs) 49{ 50 for (; *obs; obs++) 51 _obstack_free (*obs, NULL); 52 _obstack_free (&frchains, NULL); 53 _obstack_free (&cond_obstack, NULL); 54 _obstack_free (¬es, NULL); 55} 56 57static void 58alloc_seginfo (segT seg) 59{ 60 segment_info_type *seginfo; 61 62 seginfo = obstack_alloc (¬es, sizeof (*seginfo)); 63 memset (seginfo, 0, sizeof (*seginfo)); 64 seginfo->bfd_section = seg; 65 bfd_set_section_userdata (seg, seginfo); 66} 67/* 68 * subseg_change() 69 * 70 * Change the subsegment we are in, BUT DO NOT MAKE A NEW FRAG for the 71 * subsegment. If we are already in the correct subsegment, change nothing. 72 * This is used eg as a worker for subseg_set [which does make a new frag_now] 73 * and for changing segments after we have read the source. We construct eg 74 * fixSs even after the source file is read, so we do have to keep the 75 * segment context correct. 76 */ 77void 78subseg_change (segT seg, int subseg) 79{ 80 now_seg = seg; 81 now_subseg = subseg; 82 83 if (!seg_info (seg)) 84 alloc_seginfo (seg); 85} 86 87static void 88subseg_set_rest (segT seg, subsegT subseg) 89{ 90 frchainS *frcP; /* crawl frchain chain */ 91 frchainS **lastPP; /* address of last pointer */ 92 frchainS *newP; /* address of new frchain */ 93 segment_info_type *seginfo; 94 95 mri_common_symbol = NULL; 96 97 if (frag_now && frchain_now) 98 frchain_now->frch_frag_now = frag_now; 99 100 gas_assert (frchain_now == 0 101 || frchain_now->frch_last == frag_now); 102 103 subseg_change (seg, (int) subseg); 104 105 seginfo = seg_info (seg); 106 107 /* Should the section symbol be kept? */ 108 if (bfd_keep_unused_section_symbols (stdoutput)) 109 seg->symbol->flags |= BSF_SECTION_SYM_USED; 110 111 /* Attempt to find or make a frchain for that subsection. 112 We keep the list sorted by subsection number. */ 113 for (frcP = *(lastPP = &seginfo->frchainP); 114 frcP != NULL; 115 frcP = *(lastPP = &frcP->frch_next)) 116 if (frcP->frch_subseg >= subseg) 117 break; 118 119 if (frcP == NULL || frcP->frch_subseg != subseg) 120 { 121 /* This should be the only code that creates a frchainS. */ 122 123 newP = (frchainS *) obstack_alloc (&frchains, sizeof (frchainS)); 124 newP->frch_subseg = subseg; 125 newP->fix_root = NULL; 126 newP->fix_tail = NULL; 127 obstack_begin (&newP->frch_obstack, chunksize); 128#if __GNUC__ >= 2 129 obstack_alignment_mask (&newP->frch_obstack) = __alignof__ (fragS) - 1; 130#endif 131 newP->frch_frag_now = frag_alloc (&newP->frch_obstack); 132 newP->frch_frag_now->fr_type = rs_fill; 133 newP->frch_cfi_data = NULL; 134 135 newP->frch_root = newP->frch_last = newP->frch_frag_now; 136 137 *lastPP = newP; 138 newP->frch_next = frcP; 139 frcP = newP; 140 } 141 142 frchain_now = frcP; 143 frag_now = frcP->frch_frag_now; 144 145 gas_assert (frchain_now->frch_last == frag_now); 146} 147 148/* 149 * subseg_set(segT, subsegT) 150 * 151 * If you attempt to change to the current subsegment, nothing happens. 152 * 153 * In: segT, subsegT code for new subsegment. 154 * frag_now -> incomplete frag for current subsegment. 155 * If frag_now==NULL, then there is no old, incomplete frag, so 156 * the old frag is not closed off. 157 * 158 * Out: now_subseg, now_seg updated. 159 * Frchain_now points to the (possibly new) struct frchain for this 160 * sub-segment. 161 */ 162 163segT 164subseg_get (const char *segname, int force_new) 165{ 166 segT secptr; 167 const char *now_seg_name = now_seg ? bfd_section_name (now_seg) : 0; 168 169 if (!force_new 170 && now_seg_name 171 && (now_seg_name == segname 172 || !strcmp (now_seg_name, segname))) 173 return now_seg; 174 175 if (!force_new) 176 secptr = bfd_make_section_old_way (stdoutput, segname); 177 else 178 secptr = bfd_make_section_anyway (stdoutput, segname); 179 180 if (!seg_info (secptr)) 181 { 182 secptr->output_section = secptr; 183 alloc_seginfo (secptr); 184 } 185 return secptr; 186} 187 188segT 189subseg_new (const char *segname, subsegT subseg) 190{ 191 segT secptr; 192 193 secptr = subseg_get (segname, 0); 194 subseg_set_rest (secptr, subseg); 195 return secptr; 196} 197 198/* Like subseg_new, except a new section is always created, even if 199 a section with that name already exists. */ 200segT 201subseg_force_new (const char *segname, subsegT subseg) 202{ 203 segT secptr; 204 205 secptr = subseg_get (segname, 1); 206 subseg_set_rest (secptr, subseg); 207 return secptr; 208} 209 210void 211subseg_set (segT secptr, subsegT subseg) 212{ 213 if (! (secptr == now_seg && subseg == now_subseg)) 214 subseg_set_rest (secptr, subseg); 215 mri_common_symbol = NULL; 216} 217 218#ifndef obj_sec_sym_ok_for_reloc 219#define obj_sec_sym_ok_for_reloc(SEC) 0 220#endif 221 222symbolS * 223section_symbol (segT sec) 224{ 225 segment_info_type *seginfo = seg_info (sec); 226 symbolS *s; 227 228 if (seginfo == 0) 229 abort (); 230 if (seginfo->sym) 231 return seginfo->sym; 232 233#ifndef EMIT_SECTION_SYMBOLS 234#define EMIT_SECTION_SYMBOLS 1 235#endif 236 237 if (! EMIT_SECTION_SYMBOLS || symbol_table_frozen) 238 { 239 /* Here we know it won't be going into the symbol table. */ 240 s = symbol_create (sec->symbol->name, sec, &zero_address_frag, 0); 241 } 242 else 243 { 244 segT seg; 245 s = symbol_find (sec->symbol->name); 246 /* We have to make sure it is the right symbol when we 247 have multiple sections with the same section name. */ 248 if (s == NULL 249 || ((seg = S_GET_SEGMENT (s)) != sec 250 && seg != undefined_section)) 251 s = symbol_new (sec->symbol->name, sec, &zero_address_frag, 0); 252 else if (seg == undefined_section) 253 { 254 S_SET_SEGMENT (s, sec); 255 symbol_set_frag (s, &zero_address_frag); 256 } 257 } 258 259 S_CLEAR_EXTERNAL (s); 260 261 /* Use the BFD section symbol, if possible. */ 262 if (obj_sec_sym_ok_for_reloc (sec)) 263 symbol_set_bfdsym (s, sec->symbol); 264 else 265 symbol_get_bfdsym (s)->flags |= BSF_SECTION_SYM; 266 267 seginfo->sym = s; 268 return s; 269} 270 271/* Return whether the specified segment is thought to hold text. */ 272 273int 274subseg_text_p (segT sec) 275{ 276 return (bfd_section_flags (sec) & SEC_CODE) != 0; 277} 278 279/* Return non zero if SEC has at least one byte of data. It is 280 possible that we'll return zero even on a non-empty section because 281 we don't know all the fragment types, and it is possible that an 282 fr_fix == 0 one still contributes data. Think of this as 283 seg_definitely_not_empty_p. */ 284 285int 286seg_not_empty_p (segT sec ATTRIBUTE_UNUSED) 287{ 288 segment_info_type *seginfo = seg_info (sec); 289 frchainS *chain; 290 fragS *frag; 291 292 if (!seginfo) 293 return 0; 294 295 for (chain = seginfo->frchainP; chain; chain = chain->frch_next) 296 { 297 for (frag = chain->frch_root; frag; frag = frag->fr_next) 298 if (frag->fr_fix) 299 return 1; 300 if (obstack_next_free (&chain->frch_obstack) 301 != chain->frch_last->fr_literal) 302 return 1; 303 } 304 return 0; 305} 306 307void 308subsegs_print_statistics (FILE *file) 309{ 310 frchainS *frchp; 311 asection *s; 312 313 /* PR 20897 - check to see if the output bfd was actually created. */ 314 if (stdoutput == NULL) 315 return; 316 317 fprintf (file, "frag chains:\n"); 318 for (s = stdoutput->sections; s; s = s->next) 319 { 320 segment_info_type *seginfo; 321 322 /* Skip gas-internal sections. */ 323 if (segment_name (s)[0] == '*') 324 continue; 325 326 seginfo = seg_info (s); 327 if (!seginfo) 328 continue; 329 330 for (frchp = seginfo->frchainP; frchp; frchp = frchp->frch_next) 331 { 332 int count = 0; 333 fragS *fragp; 334 335 for (fragp = frchp->frch_root; fragp; fragp = fragp->fr_next) 336 count++; 337 338 fprintf (file, "\n"); 339 fprintf (file, "\t%p %-10s\t%10d frags\n", (void *) frchp, 340 segment_name (s), count); 341 } 342 } 343} 344 345/* end of subsegs.c */ 346