Coverage Report

Created: 2023-06-29 07:09

/src/binutils-gdb/gas/subsegs.c
Line
Count
Source (jump to first uncovered line)
1
/* subsegs.c - subsegments -
2
   Copyright (C) 1987-2023 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
633
{
38
633
  obstack_begin (&frchains, chunksize);
39
633
#if __GNUC__ >= 2
40
633
  obstack_alignment_mask (&frchains) = __alignof__ (frchainS) - 1;
41
633
#endif
42
43
633
  frchain_now = NULL;   /* Warn new_subseg() that we are booting.  */
44
633
  frag_now = &dummy_frag;
45
633
}
46
47
void
48
subsegs_end (struct obstack **obs)
49
633
{
50
8.35k
  for (; *obs; obs++)
51
7.71k
    _obstack_free (*obs, NULL);
52
633
  _obstack_free (&frchains, NULL);
53
633
  bfd_set_section_userdata (bfd_abs_section_ptr, NULL);
54
633
  bfd_set_section_userdata (bfd_und_section_ptr, NULL);
55
633
}
56

57
static void
58
alloc_seginfo (segT seg)
59
7.09k
{
60
7.09k
  segment_info_type *seginfo;
61
62
7.09k
  seginfo = obstack_alloc (&notes, sizeof (*seginfo));
63
7.09k
  memset (seginfo, 0, sizeof (*seginfo));
64
7.09k
  seginfo->bfd_section = seg;
65
7.09k
  bfd_set_section_userdata (seg, seginfo);
66
7.09k
}
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
 */
77
void
78
subseg_change (segT seg, int subseg)
79
17.8k
{
80
17.8k
  now_seg = seg;
81
17.8k
  now_subseg = subseg;
82
83
17.8k
  if (!seg_info (seg))
84
0
    alloc_seginfo (seg);
85
17.8k
}
86

87
static void
88
subseg_set_rest (segT seg, subsegT subseg)
89
17.8k
{
90
17.8k
  frchainS *frcP;   /* crawl frchain chain */
91
17.8k
  frchainS **lastPP;    /* address of last pointer */
92
17.8k
  frchainS *newP;   /* address of new frchain */
93
17.8k
  segment_info_type *seginfo;
94
95
17.8k
  mri_common_symbol = NULL;
96
97
17.8k
  if (frag_now && frchain_now)
98
17.1k
    frchain_now->frch_frag_now = frag_now;
99
100
17.8k
  gas_assert (frchain_now == 0
101
17.8k
    || frchain_now->frch_last == frag_now);
102
103
0
  subseg_change (seg, (int) subseg);
104
105
17.8k
  seginfo = seg_info (seg);
106
107
  /* Should the section symbol be kept?  */
108
17.8k
  if (bfd_keep_unused_section_symbols (stdoutput))
109
0
    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
17.8k
  for (frcP = *(lastPP = &seginfo->frchainP);
114
38.9k
       frcP != NULL;
115
21.1k
       frcP = *(lastPP = &frcP->frch_next))
116
31.6k
    if (frcP->frch_subseg >= subseg)
117
10.4k
      break;
118
119
17.8k
  if (frcP == NULL || frcP->frch_subseg != subseg)
120
7.71k
    {
121
      /* This should be the only code that creates a frchainS.  */
122
123
7.71k
      newP = (frchainS *) obstack_alloc (&frchains, sizeof (frchainS));
124
7.71k
      newP->frch_subseg = subseg;
125
7.71k
      newP->fix_root = NULL;
126
7.71k
      newP->fix_tail = NULL;
127
7.71k
      obstack_begin (&newP->frch_obstack, chunksize);
128
7.71k
#if __GNUC__ >= 2
129
7.71k
      obstack_alignment_mask (&newP->frch_obstack) = __alignof__ (fragS) - 1;
130
7.71k
#endif
131
7.71k
      newP->frch_frag_now = frag_alloc (&newP->frch_obstack);
132
7.71k
      newP->frch_frag_now->fr_type = rs_fill;
133
7.71k
      newP->frch_cfi_data = NULL;
134
135
7.71k
      newP->frch_root = newP->frch_last = newP->frch_frag_now;
136
137
7.71k
      *lastPP = newP;
138
7.71k
      newP->frch_next = frcP;
139
7.71k
      frcP = newP;
140
7.71k
    }
141
142
17.8k
  frchain_now = frcP;
143
17.8k
  frag_now = frcP->frch_frag_now;
144
145
17.8k
  gas_assert (frchain_now->frch_last == frag_now);
146
17.8k
}
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.10k
{
166
7.10k
  segT secptr;
167
7.10k
  const char *now_seg_name = now_seg ? bfd_section_name (now_seg) : 0;
168
169
7.10k
  if (!force_new
170
7.10k
      && now_seg_name
171
7.10k
      && (now_seg_name == segname
172
6.28k
    || !strcmp (now_seg_name, segname)))
173
0
    return now_seg;
174
175
7.10k
  if (!force_new)
176
6.91k
    secptr = bfd_make_section_old_way (stdoutput, segname);
177
188
  else
178
188
    secptr = bfd_make_section_anyway (stdoutput, segname);
179
180
7.10k
  if (!seg_info (secptr))
181
7.09k
    {
182
7.09k
      secptr->output_section = secptr;
183
7.09k
      alloc_seginfo (secptr);
184
7.09k
    }
185
7.10k
  return secptr;
186
7.10k
}
187
188
segT
189
subseg_new (const char *segname, subsegT subseg)
190
6.91k
{
191
6.91k
  segT secptr;
192
193
6.91k
  secptr = subseg_get (segname, 0);
194
6.91k
  subseg_set_rest (secptr, subseg);
195
6.91k
  return secptr;
196
6.91k
}
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
188
{
203
188
  segT secptr;
204
205
188
  secptr = subseg_get (segname, 1);
206
188
  subseg_set_rest (secptr, subseg);
207
188
  return secptr;
208
188
}
209
210
void
211
subseg_set (segT secptr, subsegT subseg)
212
16.2k
{
213
16.2k
  if (! (secptr == now_seg && subseg == now_subseg))
214
10.7k
    subseg_set_rest (secptr, subseg);
215
16.2k
  mri_common_symbol = NULL;
216
16.2k
}
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
7.51k
{
225
7.51k
  segment_info_type *seginfo = seg_info (sec);
226
7.51k
  symbolS *s;
227
228
7.51k
  if (seginfo == 0)
229
0
    abort ();
230
7.51k
  if (seginfo->sym)
231
4.81k
    return seginfo->sym;
232
233
2.70k
#ifndef EMIT_SECTION_SYMBOLS
234
5.41k
#define EMIT_SECTION_SYMBOLS 1
235
2.70k
#endif
236
237
2.70k
  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.70k
  else
243
2.70k
    {
244
2.70k
      segT seg;
245
2.70k
      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.70k
      if (s == NULL
249
2.70k
    || ((seg = S_GET_SEGMENT (s)) != sec
250
1
        && seg != undefined_section))
251
2.70k
  s = symbol_new (sec->symbol->name, sec, &zero_address_frag, 0);
252
1
      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.70k
    }
258
259
2.70k
  S_CLEAR_EXTERNAL (s);
260
261
  /* Use the BFD section symbol, if possible.  */
262
2.70k
  if (obj_sec_sym_ok_for_reloc (sec))
263
2.67k
    symbol_set_bfdsym (s, sec->symbol);
264
35
  else
265
35
    symbol_get_bfdsym (s)->flags |= BSF_SECTION_SYM;
266
267
2.70k
  seginfo->sym = s;
268
2.70k
  return s;
269
7.51k
}
270
271
/* Return whether the specified segment is thought to hold text.  */
272
273
int
274
subseg_text_p (segT sec)
275
12.1k
{
276
12.1k
  return (bfd_section_flags (sec) & SEC_CODE) != 0;
277
12.1k
}
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
3
{
288
3
  segment_info_type *seginfo = seg_info (sec);
289
3
  frchainS *chain;
290
3
  fragS *frag;
291
292
3
  if (!seginfo)
293
0
    return 0;
294
295
3
  for (chain = seginfo->frchainP; chain; chain = chain->frch_next)
296
3
    {
297
4
      for (frag = chain->frch_root; frag; frag = frag->fr_next)
298
4
  if (frag->fr_fix)
299
3
    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
3
}
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 */