Coverage Report

Created: 2023-08-28 06:31

/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
1.15k
{
38
1.15k
  obstack_begin (&frchains, chunksize);
39
1.15k
#if __GNUC__ >= 2
40
1.15k
  obstack_alignment_mask (&frchains) = __alignof__ (frchainS) - 1;
41
1.15k
#endif
42
43
1.15k
  frchain_now = NULL;   /* Warn new_subseg() that we are booting.  */
44
1.15k
  frag_now = &dummy_frag;
45
1.15k
}
46
47
void
48
subsegs_end (struct obstack **obs)
49
1.15k
{
50
15.1k
  for (; *obs; obs++)
51
13.9k
    _obstack_free (*obs, NULL);
52
1.15k
  _obstack_free (&frchains, NULL);
53
1.15k
  bfd_set_section_userdata (bfd_abs_section_ptr, NULL);
54
1.15k
  bfd_set_section_userdata (bfd_und_section_ptr, NULL);
55
1.15k
}
56

57
static void
58
alloc_seginfo (segT seg)
59
13.0k
{
60
13.0k
  segment_info_type *seginfo;
61
62
13.0k
  seginfo = obstack_alloc (&notes, sizeof (*seginfo));
63
13.0k
  memset (seginfo, 0, sizeof (*seginfo));
64
13.0k
  seginfo->bfd_section = seg;
65
13.0k
  bfd_set_section_userdata (seg, seginfo);
66
13.0k
}
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
31.7k
{
80
31.7k
  now_seg = seg;
81
31.7k
  now_subseg = subseg;
82
83
31.7k
  if (!seg_info (seg))
84
0
    alloc_seginfo (seg);
85
31.7k
}
86

87
static void
88
subseg_set_rest (segT seg, subsegT subseg)
89
31.7k
{
90
31.7k
  frchainS *frcP;   /* crawl frchain chain */
91
31.7k
  frchainS **lastPP;    /* address of last pointer */
92
31.7k
  frchainS *newP;   /* address of new frchain */
93
31.7k
  segment_info_type *seginfo;
94
95
31.7k
  mri_common_symbol = NULL;
96
97
31.7k
  if (frag_now && frchain_now)
98
30.5k
    frchain_now->frch_frag_now = frag_now;
99
100
31.7k
  gas_assert (frchain_now == 0
101
31.7k
    || frchain_now->frch_last == frag_now);
102
103
0
  subseg_change (seg, (int) subseg);
104
105
31.7k
  seginfo = seg_info (seg);
106
107
  /* Should the section symbol be kept?  */
108
31.7k
  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
31.7k
  for (frcP = *(lastPP = &seginfo->frchainP);
114
49.5k
       frcP != NULL;
115
31.7k
       frcP = *(lastPP = &frcP->frch_next))
116
36.0k
    if (frcP->frch_subseg >= subseg)
117
18.2k
      break;
118
119
31.7k
  if (frcP == NULL || frcP->frch_subseg != subseg)
120
13.9k
    {
121
      /* This should be the only code that creates a frchainS.  */
122
123
13.9k
      newP = (frchainS *) obstack_alloc (&frchains, sizeof (frchainS));
124
13.9k
      newP->frch_subseg = subseg;
125
13.9k
      newP->fix_root = NULL;
126
13.9k
      newP->fix_tail = NULL;
127
13.9k
      obstack_begin (&newP->frch_obstack, chunksize);
128
13.9k
#if __GNUC__ >= 2
129
13.9k
      obstack_alignment_mask (&newP->frch_obstack) = __alignof__ (fragS) - 1;
130
13.9k
#endif
131
13.9k
      newP->frch_frag_now = frag_alloc (&newP->frch_obstack);
132
13.9k
      newP->frch_frag_now->fr_type = rs_fill;
133
13.9k
      newP->frch_cfi_data = NULL;
134
135
13.9k
      newP->frch_root = newP->frch_last = newP->frch_frag_now;
136
137
13.9k
      *lastPP = newP;
138
13.9k
      newP->frch_next = frcP;
139
13.9k
      frcP = newP;
140
13.9k
    }
141
142
31.7k
  frchain_now = frcP;
143
31.7k
  frag_now = frcP->frch_frag_now;
144
145
31.7k
  gas_assert (frchain_now->frch_last == frag_now);
146
31.7k
}
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
13.3k
{
166
13.3k
  segT secptr;
167
13.3k
  const char *now_seg_name = now_seg ? bfd_section_name (now_seg) : 0;
168
169
13.3k
  if (!force_new
170
13.3k
      && now_seg_name
171
13.3k
      && (now_seg_name == segname
172
11.1k
    || !strcmp (now_seg_name, segname)))
173
0
    return now_seg;
174
175
13.3k
  if (!force_new)
176
12.3k
    secptr = bfd_make_section_old_way (stdoutput, segname);
177
972
  else
178
972
    secptr = bfd_make_section_anyway (stdoutput, segname);
179
180
13.3k
  if (!seg_info (secptr))
181
13.0k
    {
182
13.0k
      secptr->output_section = secptr;
183
13.0k
      alloc_seginfo (secptr);
184
13.0k
    }
185
13.3k
  return secptr;
186
13.3k
}
187
188
segT
189
subseg_new (const char *segname, subsegT subseg)
190
12.3k
{
191
12.3k
  segT secptr;
192
193
12.3k
  secptr = subseg_get (segname, 0);
194
12.3k
  subseg_set_rest (secptr, subseg);
195
12.3k
  return secptr;
196
12.3k
}
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
972
{
203
972
  segT secptr;
204
205
972
  secptr = subseg_get (segname, 1);
206
972
  subseg_set_rest (secptr, subseg);
207
972
  return secptr;
208
972
}
209
210
void
211
subseg_set (segT secptr, subsegT subseg)
212
26.1k
{
213
26.1k
  if (! (secptr == now_seg && subseg == now_subseg))
214
18.3k
    subseg_set_rest (secptr, subseg);
215
26.1k
  mri_common_symbol = NULL;
216
26.1k
}
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
37.0k
{
225
37.0k
  segment_info_type *seginfo = seg_info (sec);
226
37.0k
  symbolS *s;
227
228
37.0k
  if (seginfo == 0)
229
0
    abort ();
230
37.0k
  if (seginfo->sym)
231
31.5k
    return seginfo->sym;
232
233
5.50k
#ifndef EMIT_SECTION_SYMBOLS
234
11.0k
#define EMIT_SECTION_SYMBOLS 1
235
5.50k
#endif
236
237
5.50k
  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
5.50k
  else
243
5.50k
    {
244
5.50k
      segT seg;
245
5.50k
      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
5.50k
      if (s == NULL
249
5.50k
    || ((seg = S_GET_SEGMENT (s)) != sec
250
7
        && seg != undefined_section))
251
5.49k
  s = symbol_new (sec->symbol->name, sec, &zero_address_frag, 0);
252
6
      else if (seg == undefined_section)
253
5
  {
254
5
    S_SET_SEGMENT (s, sec);
255
5
    symbol_set_frag (s, &zero_address_frag);
256
5
  }
257
5.50k
    }
258
259
5.50k
  S_CLEAR_EXTERNAL (s);
260
261
  /* Use the BFD section symbol, if possible.  */
262
5.50k
  if (obj_sec_sym_ok_for_reloc (sec))
263
5.45k
    symbol_set_bfdsym (s, sec->symbol);
264
50
  else
265
50
    symbol_get_bfdsym (s)->flags |= BSF_SECTION_SYM;
266
267
5.50k
  seginfo->sym = s;
268
5.50k
  return s;
269
37.0k
}
270
271
/* Return whether the specified segment is thought to hold text.  */
272
273
int
274
subseg_text_p (segT sec)
275
37.2k
{
276
37.2k
  return (bfd_section_flags (sec) & SEC_CODE) != 0;
277
37.2k
}
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
19
{
288
19
  segment_info_type *seginfo = seg_info (sec);
289
19
  frchainS *chain;
290
19
  fragS *frag;
291
292
19
  if (!seginfo)
293
0
    return 0;
294
295
34
  for (chain = seginfo->frchainP; chain; chain = chain->frch_next)
296
19
    {
297
56
      for (frag = chain->frch_root; frag; frag = frag->fr_next)
298
40
  if (frag->fr_fix)
299
3
    return 1;
300
16
      if (obstack_next_free (&chain->frch_obstack)
301
16
    != chain->frch_last->fr_literal)
302
1
  return 1;
303
16
    }
304
15
  return 0;
305
19
}
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 */