Coverage Report

Created: 2025-06-24 06:45

/src/binutils-gdb/gas/scfidw2gen.c
Line
Count
Source (jump to first uncovered line)
1
/* scfidw2gen.c - Support for emission of synthesized Dwarf2 CFI.
2
   Copyright (C) 2023-2025 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
#include "as.h"
22
#include "ginsn.h"
23
#include "scfi.h"
24
#include "dw2gencfi.h"
25
#include "subsegs.h"
26
#include "scfidw2gen.h"
27
28
#if defined (TARGET_USE_SCFI) && defined (TARGET_USE_GINSN)
29
30
static bool scfi_ignore_warn_once;
31
32
static void
33
dot_scfi_ignore (int ignored ATTRIBUTE_UNUSED)
34
0
{
35
0
  gas_assert (flag_synth_cfi);
36
37
0
  if (!scfi_ignore_warn_once)
38
0
    {
39
0
      as_warn (_("SCFI ignores most user-specified CFI directives"));
40
0
      scfi_ignore_warn_once = true;
41
0
    }
42
0
  ignore_rest_of_line ();
43
0
}
44
45
static void
46
scfi_process_cfi_label (void)
47
0
{
48
0
  char *name;
49
0
  ginsnS *ginsn;
50
51
0
  name = read_symbol_name ();
52
0
  if (name == NULL)
53
0
    return;
54
55
  /* Add a new ginsn.  */
56
0
  ginsn = ginsn_new_phantom (symbol_temp_new_now ());
57
0
  frch_ginsn_data_append (ginsn);
58
59
0
  scfi_op_add_cfi_label (ginsn, name);
60
  /* NB: Can't free NAME here since it will be used later.  Free it in
61
     handle_scfi_dot_cfi after it is unused.  */
62
63
0
  demand_empty_rest_of_line ();
64
0
}
65
66
static void
67
scfi_process_cfi_signal_frame (void)
68
0
{
69
0
  ginsnS *ginsn;
70
71
0
  ginsn = ginsn_new_phantom (symbol_temp_new_now ());
72
0
  frch_ginsn_data_append (ginsn);
73
74
0
  scfi_op_add_signal_frame (ginsn);
75
0
}
76
77
static void
78
dot_scfi (int arg)
79
0
{
80
0
  switch (arg)
81
0
    {
82
0
      case CFI_label:
83
0
  scfi_process_cfi_label ();
84
0
  break;
85
0
      case CFI_signal_frame:
86
0
  scfi_process_cfi_signal_frame ();
87
0
  break;
88
0
      default:
89
0
  abort ();
90
0
    }
91
0
}
92
93
const pseudo_typeS scfi_pseudo_table[] =
94
  {
95
    { "cfi_sections", dot_cfi_sections, 0 }, /* No ignore.  */
96
    { "cfi_signal_frame", dot_scfi, CFI_signal_frame }, /* No ignore.  */
97
    { "cfi_label", dot_scfi, CFI_label }, /* No ignore.  */
98
    { "cfi_startproc", dot_scfi_ignore, 0 },
99
    { "cfi_endproc", dot_scfi_ignore, 0 },
100
    { "cfi_fde_data", dot_scfi_ignore, 0 },
101
    { "cfi_def_cfa", dot_scfi_ignore, 0 },
102
    { "cfi_def_cfa_register", dot_scfi_ignore, 0 },
103
    { "cfi_def_cfa_offset", dot_scfi_ignore, 0 },
104
    { "cfi_adjust_cfa_offset", dot_scfi_ignore, 0 },
105
    { "cfi_offset", dot_scfi_ignore, 0 },
106
    { "cfi_rel_offset", dot_scfi_ignore, 0 },
107
    { "cfi_register", dot_scfi_ignore, 0 },
108
    { "cfi_return_column", dot_scfi_ignore, 0 },
109
    { "cfi_restore", dot_scfi_ignore, 0 },
110
    { "cfi_undefined", dot_scfi_ignore, 0 },
111
    { "cfi_same_value", dot_scfi_ignore, 0 },
112
    { "cfi_remember_state", dot_scfi_ignore, 0 },
113
    { "cfi_restore_state", dot_scfi_ignore, 0 },
114
    { "cfi_window_save", dot_scfi_ignore, 0 },
115
    { "cfi_negate_ra_state", dot_scfi_ignore, 0 },
116
    { "cfi_negate_ra_state_with_pc", dot_scfi_ignore, 0 },
117
    { "cfi_escape", dot_scfi_ignore, 0 },
118
    { "cfi_personality", dot_scfi_ignore, 0 },
119
    { "cfi_personality_id", dot_scfi_ignore, 0 },
120
    { "cfi_lsda", dot_scfi_ignore, 0 },
121
    { "cfi_val_encoded_addr", dot_scfi_ignore, 0 },
122
    { "cfi_inline_lsda", dot_scfi_ignore, 0 },
123
    { "cfi_val_offset", dot_scfi_ignore, 0 },
124
    { NULL, NULL, 0 }
125
  };
126
127
void
128
scfi_dot_cfi_startproc (const symbolS *start_sym)
129
0
{
130
0
  if (frchain_now->frch_cfi_data != NULL)
131
0
    {
132
0
      as_bad (_("SCFI: missing previous SCFI endproc marker"));
133
0
      return;
134
0
    }
135
136
0
  cfi_new_fde ((symbolS *)start_sym, false);
137
138
0
  cfi_set_sections ();
139
140
0
  frchain_now->frch_cfi_data->cur_cfa_offset = 0;
141
142
  /* By default, SCFI machinery assumes .cfi_startproc is used without
143
     parameter simple.  */
144
0
  tc_cfi_frame_initial_instructions ();
145
146
0
  if ((all_cfi_sections & CFI_EMIT_target) != 0)
147
0
    tc_cfi_startproc ();
148
0
}
149
150
void
151
scfi_dot_cfi_endproc (const symbolS *end_sym)
152
0
{
153
0
  struct fde_entry *fde_last;
154
155
0
  if (frchain_now->frch_cfi_data == NULL)
156
0
    {
157
0
      as_bad (_(".cfi_endproc without corresponding .cfi_startproc"));
158
0
      return;
159
0
    }
160
161
0
  fde_last = frchain_now->frch_cfi_data->cur_fde_data;
162
0
  cfi_set_last_fde (fde_last);
163
164
0
  cfi_end_fde ((symbolS *)end_sym);
165
166
0
  if ((all_cfi_sections & CFI_EMIT_target) != 0)
167
0
    tc_cfi_endproc (fde_last);
168
0
}
169
170
void
171
scfi_dot_cfi (int arg, unsigned reg1, unsigned reg2, offsetT offset,
172
        const char *name, const symbolS *advloc)
173
0
{
174
0
  if (frchain_now->frch_cfi_data == NULL)
175
0
    {
176
0
      as_bad (_("CFI instruction used without previous .cfi_startproc"));
177
0
      return;
178
0
    }
179
180
  /* If the last address was not at the current PC, advance to current.  */
181
0
  if (frchain_now->frch_cfi_data->last_address != advloc)
182
0
    cfi_add_advance_loc ((symbolS *)advloc);
183
184
0
  switch (arg)
185
0
    {
186
0
    case DW_CFA_offset:
187
0
      cfi_add_CFA_offset (reg1, offset);
188
0
      break;
189
190
0
    case DW_CFA_val_offset:
191
0
      cfi_add_CFA_val_offset (reg1, offset);
192
0
      break;
193
194
0
    case CFI_rel_offset:
195
0
      cfi_add_CFA_offset (reg1,
196
0
        offset - frchain_now->frch_cfi_data->cur_cfa_offset);
197
0
      break;
198
199
0
    case DW_CFA_def_cfa:
200
0
      cfi_add_CFA_def_cfa (reg1, offset);
201
0
      break;
202
203
0
    case DW_CFA_register:
204
0
      cfi_add_CFA_register (reg1, reg2);
205
0
      break;
206
207
0
    case DW_CFA_def_cfa_register:
208
0
      cfi_add_CFA_def_cfa_register (reg1);
209
0
      break;
210
211
0
    case DW_CFA_def_cfa_offset:
212
0
      cfi_add_CFA_def_cfa_offset (offset);
213
0
      break;
214
215
0
    case CFI_adjust_cfa_offset:
216
0
      cfi_add_CFA_def_cfa_offset (frchain_now->frch_cfi_data->cur_cfa_offset
217
0
          + offset);
218
0
      break;
219
220
0
    case DW_CFA_restore:
221
0
      cfi_add_CFA_restore (reg1);
222
0
      break;
223
224
0
    case DW_CFA_remember_state:
225
0
      cfi_add_CFA_remember_state ();
226
0
      break;
227
228
0
    case DW_CFA_restore_state:
229
0
      cfi_add_CFA_restore_state ();
230
0
      break;
231
232
0
    case CFI_label:
233
0
      cfi_add_label (name);
234
0
      break;
235
236
0
    case CFI_signal_frame:
237
0
      frchain_now->frch_cfi_data->cur_fde_data->signal_frame = 1;
238
0
      break;
239
240
/*
241
    case DW_CFA_undefined:
242
      for (;;)
243
  {
244
    reg1 = cfi_parse_reg ();
245
    cfi_add_CFA_undefined (reg1);
246
    SKIP_WHITESPACE ();
247
    if (*input_line_pointer != ',')
248
      break;
249
    ++input_line_pointer;
250
  }
251
      break;
252
253
    case DW_CFA_same_value:
254
      reg1 = cfi_parse_reg ();
255
      cfi_add_CFA_same_value (reg1);
256
      break;
257
258
    case CFI_return_column:
259
      reg1 = cfi_parse_reg ();
260
      cfi_set_return_column (reg1);
261
      break;
262
263
    case DW_CFA_GNU_window_save:
264
      cfi_add_CFA_insn (DW_CFA_GNU_window_save);
265
      break;
266
267
*/
268
0
    default:
269
0
      abort ();
270
0
    }
271
0
}
272
273
#endif