Coverage Report

Created: 2024-05-21 06:29

/src/binutils-gdb/gas/subsegs.c
Line
Count
Source (jump to first uncovered line)
1
/* subsegs.c - subsegments -
2
   Copyright (C) 1987-2024 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
28
frchainS *frchain_now;
29
30
static struct obstack frchains;
31
32
static fragS dummy_frag;
33
34

35
void
36
subsegs_begin (void)
37
736
{
38
736
  obstack_begin (&frchains, chunksize);
39
736
#if __GNUC__ >= 2
40
736
  obstack_alignment_mask (&frchains) = __alignof__ (frchainS) - 1;
41
736
#endif
42
43
736
  frchain_now = NULL;   /* Warn new_subseg() that we are booting.  */
44
736
  frag_now = &dummy_frag;
45
736
}
46
47
void
48
subsegs_end (struct obstack **obs)
49
736
{
50
8.23k
  for (; *obs; obs++)
51
7.49k
    _obstack_free (*obs, NULL);
52
736
  _obstack_free (&frchains, NULL);
53
736
  bfd_set_section_userdata (bfd_abs_section_ptr, NULL);
54
736
  bfd_set_section_userdata (bfd_und_section_ptr, NULL);
55
736
}
56

57
static void
58
alloc_seginfo (segT seg)
59
7.43k
{
60
7.43k
  segment_info_type *seginfo;
61
62
7.43k
  seginfo = obstack_alloc (&notes, sizeof (*seginfo));
63
7.43k
  memset (seginfo, 0, sizeof (*seginfo));
64
7.43k
  bfd_set_section_userdata (seg, seginfo);
65
7.43k
}
66
/*
67
 *      subseg_change()
68
 *
69
 * Change the subsegment we are in, BUT DO NOT MAKE A NEW FRAG for the
70
 * subsegment. If we are already in the correct subsegment, change nothing.
71
 * This is used eg as a worker for subseg_set [which does make a new frag_now]
72
 * and for changing segments after we have read the source. We construct eg
73
 * fixSs even after the source file is read, so we do have to keep the
74
 * segment context correct.
75
 */
76
void
77
subseg_change (segT seg, int subseg)
78
14.4k
{
79
14.4k
  now_seg = seg;
80
14.4k
  now_subseg = subseg;
81
82
14.4k
  if (!seg_info (seg))
83
0
    alloc_seginfo (seg);
84
14.4k
}
85

86
static void
87
subseg_set_rest (segT seg, subsegT subseg)
88
14.4k
{
89
14.4k
  frchainS *frcP;   /* crawl frchain chain */
90
14.4k
  frchainS **lastPP;    /* address of last pointer */
91
14.4k
  frchainS *newP;   /* address of new frchain */
92
14.4k
  segment_info_type *seginfo;
93
94
14.4k
  mri_common_symbol = NULL;
95
96
14.4k
  if (frag_now && frchain_now)
97
13.7k
    frchain_now->frch_frag_now = frag_now;
98
99
14.4k
  gas_assert (frchain_now == 0
100
14.4k
    || frchain_now->frch_last == frag_now);
101
102
14.4k
  subseg_change (seg, (int) subseg);
103
104
14.4k
  seginfo = seg_info (seg);
105
106
  /* Should the section symbol be kept?  */
107
14.4k
  if (bfd_keep_unused_section_symbols (stdoutput))
108
0
    seg->symbol->flags |= BSF_SECTION_SYM_USED;
109
110
  /* Attempt to find or make a frchain for that subsection.
111
     We keep the list sorted by subsection number.  */
112
14.4k
  for (frcP = *(lastPP = &seginfo->frchainP);
113
15.4k
       frcP != NULL;
114
14.4k
       frcP = *(lastPP = &frcP->frch_next))
115
7.95k
    if (frcP->frch_subseg >= subseg)
116
6.99k
      break;
117
118
14.4k
  if (frcP == NULL || frcP->frch_subseg != subseg)
119
7.49k
    {
120
      /* This should be the only code that creates a frchainS.  */
121
122
7.49k
      newP = (frchainS *) obstack_alloc (&frchains, sizeof (frchainS));
123
7.49k
      newP->frch_subseg = subseg;
124
7.49k
      newP->fix_root = NULL;
125
7.49k
      newP->fix_tail = NULL;
126
7.49k
      obstack_begin (&newP->frch_obstack, chunksize);
127
7.49k
#if __GNUC__ >= 2
128
7.49k
      obstack_alignment_mask (&newP->frch_obstack) = __alignof__ (fragS) - 1;
129
7.49k
#endif
130
7.49k
      newP->frch_frag_now = frag_alloc (&newP->frch_obstack);
131
7.49k
      newP->frch_frag_now->fr_type = rs_fill;
132
7.49k
      newP->frch_cfi_data = NULL;
133
7.49k
      newP->frch_ginsn_data = NULL;
134
135
7.49k
      newP->frch_root = newP->frch_last = newP->frch_frag_now;
136
137
7.49k
      *lastPP = newP;
138
7.49k
      newP->frch_next = frcP;
139
7.49k
      frcP = newP;
140
7.49k
    }
141
142
14.4k
  frchain_now = frcP;
143
14.4k
  frag_now = frcP->frch_frag_now;
144
145
14.4k
  gas_assert (frchain_now->frch_last == frag_now);
146
14.4k
}
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
163
segT
164
subseg_get (const char *segname, int force_new)
165
7.58k
{
166
7.58k
  segT secptr;
167
7.58k
  const char *now_seg_name = now_seg ? bfd_section_name (now_seg) : 0;
168
169
7.58k
  if (!force_new
170
7.58k
      && now_seg_name
171
7.58k
      && (now_seg_name == segname
172
6.67k
    || !strcmp (now_seg_name, segname)))
173
0
    return now_seg;
174
175
7.58k
  if (!force_new)
176
7.41k
    secptr = bfd_make_section_old_way (stdoutput, segname);
177
167
  else
178
167
    secptr = bfd_make_section_anyway (stdoutput, segname);
179
180
7.58k
  if (!seg_info (secptr))
181
7.43k
    {
182
7.43k
      secptr->output_section = secptr;
183
7.43k
      alloc_seginfo (secptr);
184
7.43k
    }
185
7.58k
  return secptr;
186
7.58k
}
187
188
segT
189
subseg_new (const char *segname, subsegT subseg)
190
7.41k
{
191
7.41k
  segT secptr;
192
193
7.41k
  secptr = subseg_get (segname, 0);
194
7.41k
  subseg_set_rest (secptr, subseg);
195
7.41k
  return secptr;
196
7.41k
}
197
198
/* Like subseg_new, except a new section is always created, even if
199
   a section with that name already exists.  */
200
segT
201
subseg_force_new (const char *segname, subsegT subseg)
202
167
{
203
167
  segT secptr;
204
205
167
  secptr = subseg_get (segname, 1);
206
167
  subseg_set_rest (secptr, subseg);
207
167
  return secptr;
208
167
}
209
210
void
211
subseg_set (segT secptr, subsegT subseg)
212
14.7k
{
213
14.7k
  if (! (secptr == now_seg && subseg == now_subseg))
214
6.89k
    subseg_set_rest (secptr, subseg);
215
14.7k
  mri_common_symbol = NULL;
216
14.7k
}
217
218
#ifndef obj_sec_sym_ok_for_reloc
219
#define obj_sec_sym_ok_for_reloc(SEC) 0
220
#endif
221
222
symbolS *
223
section_symbol (segT sec)
224
2.73k
{
225
2.73k
  segment_info_type *seginfo = seg_info (sec);
226
2.73k
  symbolS *s;
227
228
2.73k
  if (seginfo == 0)
229
0
    abort ();
230
2.73k
  if (seginfo->sym)
231
57
    return seginfo->sym;
232
233
2.67k
#ifndef EMIT_SECTION_SYMBOLS
234
5.35k
#define EMIT_SECTION_SYMBOLS 1
235
2.67k
#endif
236
237
2.67k
  if (! EMIT_SECTION_SYMBOLS || symbol_table_frozen)
238
0
    {
239
      /* Here we know it won't be going into the symbol table.  */
240
0
      s = symbol_create (sec->symbol->name, sec, &zero_address_frag, 0);
241
0
    }
242
2.67k
  else
243
2.67k
    {
244
2.67k
      segT seg;
245
2.67k
      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
2.67k
      if (s == NULL
249
2.67k
    || ((seg = S_GET_SEGMENT (s)) != sec
250
0
        && seg != undefined_section))
251
2.67k
  s = symbol_new (sec->symbol->name, sec, &zero_address_frag, 0);
252
0
      else if (seg == undefined_section)
253
0
  {
254
0
    S_SET_SEGMENT (s, sec);
255
0
    symbol_set_frag (s, &zero_address_frag);
256
0
  }
257
2.67k
    }
258
259
2.67k
  S_CLEAR_EXTERNAL (s);
260
261
  /* Use the BFD section symbol, if possible.  */
262
2.67k
  if (obj_sec_sym_ok_for_reloc (sec))
263
2.67k
    symbol_set_bfdsym (s, sec->symbol);
264
4
  else
265
4
    symbol_get_bfdsym (s)->flags |= BSF_SECTION_SYM;
266
267
2.67k
  seginfo->sym = s;
268
2.67k
  return s;
269
2.73k
}
270
271
/* Return whether the specified segment is thought to hold text.  */
272
273
int
274
subseg_text_p (segT sec)
275
13.0k
{
276
13.0k
  return (bfd_section_flags (sec) & SEC_CODE) != 0;
277
13.0k
}
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
285
int
286
seg_not_empty_p (segT sec ATTRIBUTE_UNUSED)
287
0
{
288
0
  segment_info_type *seginfo = seg_info (sec);
289
0
  frchainS *chain;
290
0
  fragS *frag;
291
292
0
  if (!seginfo)
293
0
    return 0;
294
295
0
  for (chain = seginfo->frchainP; chain; chain = chain->frch_next)
296
0
    {
297
0
      for (frag = chain->frch_root; frag; frag = frag->fr_next)
298
0
  if (frag->fr_fix)
299
0
    return 1;
300
0
      if (obstack_next_free (&chain->frch_obstack)
301
0
    != chain->frch_last->fr_literal)
302
0
  return 1;
303
0
    }
304
0
  return 0;
305
0
}
306
307
void
308
subsegs_print_statistics (FILE *file)
309
0
{
310
0
  frchainS *frchp;
311
0
  asection *s;
312
313
  /* PR 20897 - check to see if the output bfd was actually created.  */
314
0
  if (stdoutput == NULL)
315
0
    return;
316
317
0
  fprintf (file, "frag chains:\n");
318
0
  for (s = stdoutput->sections; s; s = s->next)
319
0
    {
320
0
      segment_info_type *seginfo;
321
322
      /* Skip gas-internal sections.  */
323
0
      if (segment_name (s)[0] == '*')
324
0
  continue;
325
326
0
      seginfo = seg_info (s);
327
0
      if (!seginfo)
328
0
  continue;
329
330
0
      for (frchp = seginfo->frchainP; frchp; frchp = frchp->frch_next)
331
0
  {
332
0
    int count = 0;
333
0
    fragS *fragp;
334
335
0
    for (fragp = frchp->frch_root; fragp; fragp = fragp->fr_next)
336
0
      count++;
337
338
0
    fprintf (file, "\n");
339
0
    fprintf (file, "\t%p %-10s\t%10d frags\n", (void *) frchp,
340
0
       segment_name (s), count);
341
0
  }
342
0
    }
343
0
}
344
345
/* end of subsegs.c */