Coverage Report

Created: 2026-07-25 10:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/binutils-gdb/gas/gen-sframe.c
Line
Count
Source
1
/* gen-sframe.c - Support for generating SFrame section.
2
   Copyright (C) 2022-2026 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 "subsegs.h"
23
#include "sframe.h"
24
#include "sframe-internal.h"
25
#include "gen-sframe.h"
26
#include "dw2gencfi.h"
27
#include "leb128.h"
28
29
#ifdef support_sframe_p
30
31
#ifndef sizeof_member
32
186
# define sizeof_member(type, member)  (sizeof (((type *)0)->member))
33
#endif
34
35
/* SFrame FRE type selection optimization is an optimization for size.
36
37
   There are three flavors of SFrame FRE representation in the binary format:
38
     - sframe_frame_row_entry_addr1 where the FRE start address is 1 byte.
39
     - sframe_frame_row_entry_addr2 where the FRE start address is 2 bytes.
40
     - sframe_frame_row_entry_addr4 where the FRE start address is 4 bytes.
41
42
   Note that in the SFrame format, all SFrame FREs of a function use one
43
   single representation.  The SFrame FRE type itself is identified via the
44
   information in the SFrame FDE function info.
45
46
   Now, to select the minimum required one from the list above, one needs to
47
   make a decision based on the size (in bytes) of the function.
48
49
   As a result, for this optimization, some fragments (generated with a new
50
   type rs_sframe) for the SFrame section are fixed up later.
51
52
   This optimization (for size) is enabled by default.  */
53
54
#ifndef SFRAME_FRE_TYPE_SELECTION_OPT
55
82
# define SFRAME_FRE_TYPE_SELECTION_OPT 1
56
#endif
57
58
/* gas emits SFrame Version 3 only at this time.  */
59
typedef sframe_func_desc_idx_v3 sframe_func_desc_idx;
60
61
/* List of SFrame FDE entries.  */
62
63
static struct sframe_func_entry *all_sframe_fdes = NULL;
64
65
/* Tail of the list to add to.  */
66
67
static struct sframe_func_entry **last_sframe_fde = &all_sframe_fdes;
68
69
/* Emit a single byte into the current segment.  */
70
71
static inline void
72
out_one (int byte)
73
381
{
74
381
  FRAG_APPEND_1_CHAR (byte);
75
381
}
76
77
/* Emit a two-byte word into the current segment.  */
78
79
static inline void
80
out_two (int data)
81
85
{
82
85
  md_number_to_chars (frag_more (2), data, 2);
83
85
}
84
85
/* Emit a four byte word into the current segment.  */
86
87
static inline void
88
out_four (int data)
89
90
{
90
90
  md_number_to_chars (frag_more (4), data, 4);
91
90
}
92
93
/* Get the start address symbol from the DWARF FDE.  */
94
95
static symbolS*
96
get_dw_fde_start_addrS (const struct fde_entry *dw_fde)
97
146
{
98
146
  return dw_fde->start_address;
99
146
}
100
101
/* Get the start address symbol from the DWARF FDE.  */
102
103
static symbolS*
104
get_dw_fde_end_addrS (const struct fde_entry *dw_fde)
105
136
{
106
136
  return dw_fde->end_address;
107
136
}
108
109
/* Get whether PAUTH B key is used.  */
110
static bool
111
get_dw_fde_pauth_b_key_p (const struct fde_entry *dw_fde ATTRIBUTE_UNUSED)
112
27
{
113
#ifdef tc_fde_entry_extras
114
  return (dw_fde->pauth_key == AARCH64_PAUTH_KEY_B);
115
#else
116
27
  return false;
117
27
#endif
118
27
}
119
120
/* Get whether signal frame.  */
121
static bool
122
get_dw_fde_signal_p (const struct fde_entry *dw_fde)
123
37
{
124
37
  return (dw_fde->signal_frame == 1);
125
37
}
126
127
/* SFrame Frame Row Entry (FRE) related functions.  */
128
129
static void
130
sframe_fre_set_begin_addr (struct sframe_row_entry *fre, symbolS *beginS)
131
84
{
132
84
  fre->pc_begin = beginS;
133
84
}
134
135
static void
136
sframe_fre_set_end_addr (struct sframe_row_entry *fre, symbolS *endS)
137
47
{
138
47
  fre->pc_end = endS;
139
47
}
140
141
static void
142
sframe_fre_set_cfa_base_reg (struct sframe_row_entry *fre,
143
           unsigned int cfa_base_reg)
144
67
{
145
67
  fre->cfa_base_reg = cfa_base_reg;
146
67
  fre->merge_candidate = false;
147
67
}
148
149
static offsetT
150
sframe_fre_get_cfa_offset (const struct sframe_row_entry * fre)
151
12
{
152
12
  offsetT offset = fre->cfa_offset;
153
154
  /* For s390x undo adjustment of CFA offset (to enable 8-bit offsets).  */
155
12
  if (sframe_get_abi_arch () == SFRAME_ABI_S390X_ENDIAN_BIG)
156
0
    offset = SFRAME_V2_S390X_CFA_OFFSET_DECODE (offset);
157
158
12
  return offset;
159
12
}
160
161
/* All stack offsets in SFrame stack trace format must be representable as a
162
   1-byte (SFRAME_FRE_DATAWORD_1B), 2-byte (SFRAME_FRE_DATAWORD_2B) or 4-byte
163
   (SFRAME_FRE_DATAWORD_4B) value.
164
165
   At the moment, sanity check on CFA offset (only) is performed to address PR
166
   gas/33277.  Arguably, such updates to ra_offset or fp_offset will only
167
   follow after updates to cfa_offset in a real-world, useful program.  */
168
169
static bool
170
sframe_fre_stack_offset_bound_p (offsetT offset, bool cfa_reg_p)
171
64
{
172
  /* For s390x, CFA offset is adjusted to enable 8-bit offsets.  */
173
64
  if (cfa_reg_p && sframe_get_abi_arch () == SFRAME_ABI_S390X_ENDIAN_BIG)
174
0
    offset = SFRAME_V2_S390X_CFA_OFFSET_ENCODE (offset);
175
176
64
  return (offset >= INT32_MIN && offset <= INT32_MAX);
177
64
}
178
179
static void
180
sframe_fre_set_cfa_offset (struct sframe_row_entry *fre,
181
         offsetT cfa_offset)
182
74
{
183
  /* For s390x adjust CFA offset to enable 8-bit offsets.  */
184
74
  if (sframe_get_abi_arch () == SFRAME_ABI_S390X_ENDIAN_BIG)
185
0
    cfa_offset = SFRAME_V2_S390X_CFA_OFFSET_ENCODE (cfa_offset);
186
187
74
  fre->cfa_offset = cfa_offset;
188
74
  fre->merge_candidate = false;
189
74
}
190
191
static void
192
sframe_fre_set_ra_track (struct sframe_row_entry *fre, offsetT ra_offset)
193
4
{
194
4
  fre->ra_loc = SFRAME_FRE_ELEM_LOC_STACK;
195
4
  fre->ra_offset = ra_offset;
196
4
  fre->ra_undefined_p = false;
197
4
  fre->merge_candidate = false;
198
4
}
199
200
static void
201
sframe_fre_set_fp_track (struct sframe_row_entry *fre, offsetT fp_offset)
202
8
{
203
8
  fre->fp_loc = SFRAME_FRE_ELEM_LOC_STACK;
204
8
  fre->fp_offset = fp_offset;
205
8
  fre->merge_candidate = false;
206
8
}
207
208
/* Given a signed offset, return the size in bytes needed to represent it.  */
209
210
static unsigned int
211
get_offset_size_in_bytes (offsetT value)
212
65
{
213
65
  unsigned int size = 0;
214
215
65
  if (value == (int8_t)value)
216
48
    size = 1;
217
17
  else if (value == (int16_t)value)
218
7
    size = 2;
219
10
  else if (value == (int32_t)value)
220
10
    size = 4;
221
0
  else
222
0
    return 8;
223
224
65
  return size;
225
65
}
226
227
/* Given an unsigned item, return the size in bytes needed to represent it.  */
228
229
static unsigned int
230
get_udata_size_in_bytes (unsigned int value)
231
21
{
232
21
  unsigned int size = 0;
233
234
21
  if (value <= UINT8_MAX)
235
19
    size = 1;
236
2
  else if (value <= UINT16_MAX)
237
2
    size = 2;
238
0
  else
239
0
    size = 4;
240
241
21
  return size;
242
21
}
243
41
#define SFRAME_FRE_DATAWORD_FUNC_MAP_INDEX_1B  0 /* SFRAME_FRE_DATAWORD_1B.  */
244
6
#define SFRAME_FRE_DATAWORD_FUNC_MAP_INDEX_2B  1 /* SFRAME_FRE_DATAWORD_2B.  */
245
8
#define SFRAME_FRE_DATAWORD_FUNC_MAP_INDEX_4B  2 /* SFRAME_FRE_DATAWORD_4B.  */
246
55
#define SFRAME_FRE_DATAWORD_FUNC_MAP_INDEX_8B  3 /* Not supported in SFrame.  */
247
#define SFRAME_FRE_DATAWORD_FUNC_MAP_INDEX_MAX \
248
55
  SFRAME_FRE_DATAWORD_FUNC_MAP_INDEX_8B
249
250
/* Helper struct for mapping FRE data word size to output functions.  */
251
252
struct sframe_fre_dataword_func_map
253
{
254
  unsigned int dataword_size;
255
  void (*out_func)(int);
256
};
257
258
/* Given an DATAWORD_SIZE, return the size in bytes needed to represent it.  */
259
260
static unsigned int
261
sframe_fre_dataword_func_map_index (unsigned int dataword_size)
262
55
{
263
55
  unsigned int idx = SFRAME_FRE_DATAWORD_FUNC_MAP_INDEX_MAX;
264
265
55
  switch (dataword_size)
266
55
    {
267
41
      case SFRAME_FRE_DATAWORD_1B:
268
41
  idx = SFRAME_FRE_DATAWORD_FUNC_MAP_INDEX_1B;
269
41
  break;
270
6
      case SFRAME_FRE_DATAWORD_2B:
271
6
  idx = SFRAME_FRE_DATAWORD_FUNC_MAP_INDEX_2B;
272
6
  break;
273
8
      case SFRAME_FRE_DATAWORD_4B:
274
8
  idx = SFRAME_FRE_DATAWORD_FUNC_MAP_INDEX_4B;
275
8
  break;
276
0
      default:
277
  /* Not supported in SFrame.  */
278
0
  break;
279
55
    }
280
281
55
  return idx;
282
55
}
283
284
/* Mapping from data word size to the output function to emit the value.  */
285
286
static const
287
struct sframe_fre_dataword_func_map
288
dataword_func_map[SFRAME_FRE_DATAWORD_FUNC_MAP_INDEX_MAX+1] =
289
{
290
  { SFRAME_FRE_DATAWORD_1B, out_one },
291
  { SFRAME_FRE_DATAWORD_2B, out_two },
292
  { SFRAME_FRE_DATAWORD_4B, out_four },
293
  { -1, NULL } /* Not Supported in SFrame.  */
294
};
295
296
/* SFrame version specific operations access.  */
297
298
static struct sframe_version_ops sframe_ver_ops;
299
300
/* SFrame (SFRAME_VERSION_1) set FRE info.  */
301
302
static unsigned char
303
sframe_v1_set_fre_info (unsigned int cfa_base_reg, unsigned int dataword_count,
304
      unsigned int dataword_size, bool mangled_ra_p)
305
55
{
306
55
  unsigned char fre_info;
307
55
  fre_info = SFRAME_V1_FRE_INFO (cfa_base_reg, dataword_count, dataword_size);
308
55
  fre_info = SFRAME_V1_FRE_INFO_UPDATE_MANGLED_RA_P (mangled_ra_p, fre_info);
309
55
  return fre_info;
310
55
}
311
312
/* SFrame (SFRAME_VERSION_3) set function info.  */
313
314
static unsigned char
315
sframe_v3_set_func_info (unsigned int fde_pc_type, unsigned int fre_type,
316
       unsigned int pauth_key, bool signal_p)
317
27
{
318
27
  unsigned char func_info;
319
27
  func_info = SFRAME_V3_FDE_FUNC_INFO (fde_pc_type, fre_type);
320
27
  func_info = SFRAME_V3_FDE_UPDATE_PAUTH_KEY (pauth_key, func_info);
321
27
  func_info = SFRAME_V3_FDE_UPDATE_SIGNAL_P (signal_p, func_info);
322
27
  return func_info;
323
27
}
324
325
/* SFrame version specific operations setup.  */
326
327
static void
328
sframe_set_version (enum gen_sframe_version flag_ver)
329
35
{
330
35
  if (flag_ver == GEN_SFRAME_VERSION_3)
331
35
    {
332
35
      sframe_ver_ops.format_version = SFRAME_VERSION_3;
333
      /* These operations remain the same for SFRAME_VERSION_3 as fre_info and
334
   func_info layout has not changed from SFRAME_VERSION_2 and
335
   SFRAME_VERSION_1.  */
336
35
      sframe_ver_ops.set_fre_info = sframe_v1_set_fre_info;
337
35
      sframe_ver_ops.set_func_info = sframe_v3_set_func_info;
338
35
    }
339
35
}
340
341
/* SFrame set FRE info.  */
342
343
static unsigned char
344
sframe_set_fre_info (unsigned int cfa_base_reg, unsigned int dataword_count,
345
         unsigned int dataword_size, bool mangled_ra_p)
346
55
{
347
55
  return sframe_ver_ops.set_fre_info (cfa_base_reg, dataword_count,
348
55
              dataword_size, mangled_ra_p);
349
55
}
350
351
/* SFrame set func info. */
352
353
static unsigned char
354
sframe_set_func_info (unsigned int fde_type, unsigned int fre_type,
355
          unsigned int pauth_key, bool signal_p)
356
27
{
357
27
  return sframe_ver_ops.set_func_info (fde_type, fre_type, pauth_key,
358
27
               signal_p);
359
27
}
360
361
/* Get the number of SFrame FDEs for the current file.  */
362
363
static unsigned int
364
get_num_sframe_fdes (void);
365
366
/* Get the number of SFrame frame row entries for the current file.  */
367
368
static unsigned int
369
get_num_sframe_fres (void);
370
371
/* Get CFA base register ID as represented in SFrame Frame Row Entry.  */
372
373
static unsigned int
374
get_fre_base_reg_id (const struct sframe_row_entry *sframe_fre)
375
55
{
376
55
  unsigned int cfi_insn_cfa_base_reg = sframe_fre->cfa_base_reg;
377
55
  unsigned fre_base_reg = SFRAME_BASE_REG_SP;
378
379
55
  if (cfi_insn_cfa_base_reg == SFRAME_CFA_FP_REG)
380
8
    fre_base_reg = SFRAME_BASE_REG_FP;
381
382
  /* Only one bit is reserved in SFRAME_VERSION_1.  */
383
55
  gas_assert (fre_base_reg == SFRAME_BASE_REG_SP
384
55
        || fre_base_reg == SFRAME_BASE_REG_FP);
385
386
55
  return fre_base_reg;
387
55
}
388
389
/* Get number of data words necessary for the SFrame Frame Row Entry.  */
390
391
static unsigned int
392
get_fre_dataword_count (const struct sframe_row_entry *sframe_fre, bool flex_p)
393
55
{
394
  /* For SFRAME_FDE_TYPE_FLEX FDE type, each entity (CFA, FP, RA) may carry up
395
     to two data words.  */
396
55
  unsigned int count = flex_p ? 2 : 1;
397
398
  /* CFA data word (or data words when flex_p) must always be present.  */
399
55
  unsigned int fre_dataword_count = count;
400
401
  /* For flexible FDE type, there will be two data words for RA (if RA
402
     has a recovery rule applicable).  1 padding data word otherwise.  */
403
55
  if (flex_p)
404
21
    {
405
21
     if (sframe_fre->ra_loc != SFRAME_FRE_ELEM_LOC_NONE)
406
4
       fre_dataword_count += count;
407
17
     else if (sframe_fre->fp_loc != SFRAME_FRE_ELEM_LOC_NONE)
408
4
       fre_dataword_count += 1;
409
21
    }
410
34
  else if (sframe_ra_tracking_p ()
411
0
     && (sframe_fre->ra_loc != SFRAME_FRE_ELEM_LOC_NONE
412
         /* For s390x account padding RA data word, if FP without RA
413
      saved.  */
414
0
         || (sframe_get_abi_arch () == SFRAME_ABI_S390X_ENDIAN_BIG
415
0
       && sframe_fre->fp_loc != SFRAME_FRE_ELEM_LOC_NONE)))
416
0
    fre_dataword_count++;
417
418
55
  if (sframe_fre->fp_loc != SFRAME_FRE_ELEM_LOC_NONE)
419
10
    fre_dataword_count += count;
420
421
55
  return fre_dataword_count;
422
55
}
423
424
/* Get the minimum necessary data word size (in bytes) for this
425
   SFrame frame row entry.  */
426
427
static unsigned int
428
sframe_get_fre_dataword_size (const struct sframe_row_entry *sframe_fre,
429
          bool flex_p)
430
55
{
431
55
  unsigned int max_dataword_size = 0;
432
55
  unsigned int cfa_offset_size = 0;
433
55
  unsigned int fp_offset_size = 0;
434
55
  unsigned int ra_offset_size = 0;
435
436
55
  unsigned int fre_dataword_size = 0;
437
438
  /* What size of data words appear in this frame row entry.  */
439
55
  cfa_offset_size = get_offset_size_in_bytes (sframe_fre->cfa_offset);
440
55
  if (sframe_fre->fp_loc == SFRAME_FRE_ELEM_LOC_STACK)
441
10
    fp_offset_size = get_offset_size_in_bytes (sframe_fre->fp_offset);
442
55
  if (sframe_ra_tracking_p ())
443
0
    {
444
0
      if (sframe_fre->ra_loc == SFRAME_FRE_ELEM_LOC_STACK)
445
0
  ra_offset_size = get_offset_size_in_bytes (sframe_fre->ra_offset);
446
      /* For s390x account padding RA offset, if FP without RA saved.  */
447
0
      else if (sframe_get_abi_arch () == SFRAME_ABI_S390X_ENDIAN_BIG
448
0
         && sframe_fre->fp_loc == SFRAME_FRE_ELEM_LOC_STACK)
449
0
  ra_offset_size = get_offset_size_in_bytes (SFRAME_FRE_RA_OFFSET_INVALID);
450
0
    }
451
452
  /* Get the maximum size needed to represent the offsets.  */
453
55
  max_dataword_size = cfa_offset_size;
454
55
  if (fp_offset_size > max_dataword_size)
455
0
    max_dataword_size = fp_offset_size;
456
55
  if (ra_offset_size > max_dataword_size)
457
0
    max_dataword_size = ra_offset_size;
458
459
  /* If flex FDE, account for reg data too.  */
460
55
  if (flex_p)
461
21
    {
462
21
      bool reg_p = (sframe_fre->cfa_base_reg != SFRAME_FRE_REG_INVALID);
463
21
      unsigned int data
464
21
  = SFRAME_V3_FLEX_FDE_CTRLWORD_ENCODE (sframe_fre->cfa_base_reg,
465
21
                sframe_fre->cfa_deref_p, reg_p);
466
21
      unsigned int cfa_control_word_size = get_udata_size_in_bytes (data);
467
21
      if (cfa_control_word_size > max_dataword_size)
468
1
  max_dataword_size = cfa_control_word_size;
469
470
21
      if (sframe_fre->ra_loc == SFRAME_FRE_ELEM_LOC_REG)
471
0
  {
472
0
    data = SFRAME_V3_FLEX_FDE_CTRLWORD_ENCODE (sframe_fre->ra_reg,
473
0
                 sframe_fre->ra_deref_p,
474
0
                 1 /* reg_p.  */);
475
0
    unsigned ra_control_word_size = get_udata_size_in_bytes (data);
476
0
    if (ra_control_word_size > max_dataword_size)
477
0
      max_dataword_size = ra_control_word_size;
478
0
  }
479
480
21
      if (sframe_fre->fp_loc == SFRAME_FRE_ELEM_LOC_REG)
481
0
  {
482
0
    data = SFRAME_V3_FLEX_FDE_CTRLWORD_ENCODE (sframe_fre->fp_reg,
483
0
                 sframe_fre->fp_deref_p,
484
0
                 1 /* reg_p.  */);
485
0
    unsigned fp_control_word_size = get_udata_size_in_bytes (data);
486
0
    if (fp_control_word_size > max_dataword_size)
487
0
      max_dataword_size = fp_control_word_size;
488
0
  }
489
21
    }
490
491
55
  gas_assert (max_dataword_size);
492
493
55
  switch (max_dataword_size)
494
55
    {
495
41
    case 1:
496
41
      fre_dataword_size = SFRAME_FRE_DATAWORD_1B;
497
41
      break;
498
6
    case 2:
499
6
      fre_dataword_size = SFRAME_FRE_DATAWORD_2B;
500
6
      break;
501
8
    case 4:
502
8
      fre_dataword_size = SFRAME_FRE_DATAWORD_4B;
503
8
      break;
504
0
    default:
505
      /* FRE data words of size 8 bytes is not supported in SFrame.  */
506
0
      as_fatal (_("SFrame unsupported FRE data word size\n"));
507
0
      break;
508
55
    }
509
510
55
  return fre_dataword_size;
511
55
}
512
513
/* Create a composite expression CEXP (for SFrame FRE start address) such that:
514
515
      exp = <val> OP_absent <width>, where,
516
517
    - <val> and <width> are themselves expressionS.
518
    - <val> stores the expression which when evaluated gives the value of the
519
      start address offset of the FRE.
520
    - <width> stores the expression when evaluated gives the number of bytes
521
      needed to encode the start address offset of the FRE.
522
523
   The use of OP_absent as the X_op_symbol helps identify this expression
524
   later when fragments are fixed up.  */
525
526
static void
527
create_fre_start_addr_exp (expressionS *cexp, symbolS *fre_pc_begin,
528
         symbolS *fde_start_address,
529
         symbolS *fde_end_address)
530
55
{
531
  /* val expression stores the FDE start address offset from the start PC
532
     of function.  */
533
55
  expressionS val = {
534
55
    .X_op = O_subtract,
535
55
    .X_add_symbol = fre_pc_begin,
536
55
    .X_op_symbol = fde_start_address,
537
55
  };
538
539
  /* width expressions stores the size of the function.  This is used later
540
     to determine the number of bytes to be used to encode the FRE start
541
     address of each FRE of the function.  */
542
55
  expressionS width = {
543
55
    .X_op = O_subtract,
544
55
    .X_add_symbol = fde_end_address,
545
55
    .X_op_symbol = fde_start_address,
546
55
  };
547
548
55
  *cexp = (expressionS) {
549
55
    .X_op = O_absent,
550
55
    .X_add_symbol = make_expr_symbol (&val),
551
55
    .X_op_symbol = make_expr_symbol (&width)
552
55
  };
553
55
}
554
555
/* Create a composite expression CEXP (for SFrame FDE function info) such that:
556
557
      exp = <rest_of_func_info> OP_modulus <width>, where,
558
559
    - <rest_of_func_info> and <width> are themselves expressionS.
560
    - <rest_of_func_info> stores a constant expression where X_add_number is
561
    used to stash away the func_info.  The upper 4-bits of the func_info are copied
562
    back to the resulting byte by the fragment fixup logic.
563
    - <width> stores the expression when evaluated gives the size of the
564
    function in number of bytes.
565
566
   The use of OP_modulus as the X_op_symbol helps identify this expression
567
   later when fragments are fixed up.  */
568
569
static void
570
create_func_info_exp (expressionS *cexp, symbolS *dw_fde_end_addrS,
571
          symbolS *dw_fde_start_addrS, uint8_t func_info)
572
27
{
573
27
  expressionS width = {
574
27
    .X_op = O_subtract,
575
27
    .X_add_symbol = dw_fde_end_addrS,
576
27
    .X_op_symbol = dw_fde_start_addrS
577
27
  };
578
579
27
  expressionS rest_of_func_info = {
580
27
    .X_op = O_constant,
581
27
    .X_add_number = func_info
582
27
  };
583
584
27
  *cexp = (expressionS) {
585
27
    .X_op = O_modulus,
586
27
    .X_add_symbol = make_expr_symbol (&rest_of_func_info),
587
27
    .X_op_symbol = make_expr_symbol (&width)
588
27
  };
589
27
}
590
591
static struct sframe_row_entry*
592
sframe_row_entry_new (void)
593
72
{
594
72
  struct sframe_row_entry *fre = XCNEW (struct sframe_row_entry);
595
  /* Reset all regs to SFRAME_FRE_REG_INVALID.  A value of 0 may imply a
596
     valid register for a supported arch.  */
597
72
  fre->cfa_base_reg = SFRAME_FRE_REG_INVALID;
598
72
  fre->fp_reg = SFRAME_FRE_REG_INVALID;
599
72
  fre->ra_reg = SFRAME_FRE_REG_INVALID;
600
72
  fre->merge_candidate = true;
601
  /* Reset the mangled RA status bit to zero by default.  We will
602
     initialize it in sframe_row_entry_initialize () with the sticky
603
     bit if set.  */
604
72
  fre->mangled_ra_p = false;
605
  /* Reset the RA undefined status by to zero by default.  */
606
72
  fre->ra_undefined_p = false;
607
608
72
  return fre;
609
72
}
610
611
static void
612
sframe_row_entry_free (struct sframe_row_entry *fre)
613
37
{
614
99
  while (fre)
615
62
    {
616
62
      struct sframe_row_entry *fre_next = fre->next;
617
62
      XDELETE (fre);
618
62
      fre = fre_next;
619
62
    }
620
37
}
621
622
/* Allocate an SFrame FDE.  */
623
624
static struct sframe_func_entry*
625
sframe_fde_alloc (void)
626
37
{
627
37
  return XCNEW (struct sframe_func_entry);
628
37
}
629
630
/* Free up the SFrame FDE.  */
631
632
static void
633
sframe_fde_free (struct sframe_func_entry *sframe_fde)
634
37
{
635
37
  if (sframe_fde == NULL)
636
0
    return;
637
638
37
  if (sframe_fde->sframe_fres)
639
27
    sframe_row_entry_free (sframe_fde->sframe_fres);
640
641
37
  XDELETE (sframe_fde);
642
37
}
643
644
/* Output the varlen data (SFrame FRE data words) for SFrame FRE object
645
   SFRAME_FRE of the SFrame FDE object SFRAME_FDE.  Each emitted entry is of
646
   size FRE_DATAWORD_SIZE.  Write out the data words in order - CFA, RA, FP.  */
647
648
static unsigned int
649
output_sframe_row_entry_datawords (const struct sframe_func_entry *sframe_fde,
650
           const struct sframe_row_entry *sframe_fre,
651
           unsigned int fre_dataword_size)
652
55
{
653
55
  unsigned int fre_write_datawords = 0;
654
655
55
  unsigned int idx = sframe_fre_dataword_func_map_index (fre_dataword_size);
656
55
  gas_assert (idx < SFRAME_FRE_DATAWORD_FUNC_MAP_INDEX_MAX);
657
658
55
  if (sframe_fde->fde_flex_p)
659
21
    {
660
      /* SFrame FDE of type SFRAME_FDE_TYPE_FLEX.  */
661
      /* Output CFA related FRE data words.  */
662
21
      uint32_t reg = sframe_fre->cfa_base_reg;
663
21
      bool deref_p = sframe_fre->cfa_deref_p;
664
21
      uint32_t reg_data
665
21
  = SFRAME_V3_FLEX_FDE_CTRLWORD_ENCODE (reg, deref_p, 1 /* reg_p.  */);
666
21
      offsetT offset_data = sframe_fre->cfa_offset;
667
21
      dataword_func_map[idx].out_func (reg_data);
668
21
      dataword_func_map[idx].out_func (offset_data);
669
21
      fre_write_datawords += 2;
670
671
21
      bool reg_p = false;
672
21
      if (sframe_fre->ra_loc != SFRAME_FRE_ELEM_LOC_NONE)
673
4
  {
674
    /* Output RA related FRE data words.  */
675
4
    reg_p = sframe_fre->ra_loc == SFRAME_FRE_ELEM_LOC_REG;
676
4
    reg = reg_p ? sframe_fre->ra_reg : 0;
677
4
    deref_p = sframe_fre->ra_deref_p;
678
4
    reg_data = SFRAME_V3_FLEX_FDE_CTRLWORD_ENCODE (reg, deref_p, reg_p);
679
680
4
    offset_data = sframe_fre->ra_offset;
681
4
    dataword_func_map[idx].out_func (reg_data);
682
4
    dataword_func_map[idx].out_func (offset_data);
683
4
    fre_write_datawords += 2;
684
4
  }
685
17
      else if (sframe_fre->fp_loc != SFRAME_FRE_ELEM_LOC_NONE)
686
4
  {
687
    /* If RA is not in REG/STACK, emit RA padding if there are more
688
       data words to follow.  Note that, emitting
689
       SFRAME_FRE_RA_OFFSET_INVALID is equivalent to emitting
690
       SFRAME_V3_FLEX_FDE_CTRLWORD_ENCODE (0, 0, 0).  */
691
4
    dataword_func_map[idx].out_func (SFRAME_FRE_RA_OFFSET_INVALID);
692
4
    fre_write_datawords += 1;
693
4
  }
694
695
21
      if (sframe_fre->fp_loc != SFRAME_FRE_ELEM_LOC_NONE)
696
7
  {
697
    /* Output FP related FRE data words.  */
698
7
    reg_p = sframe_fre->fp_loc == SFRAME_FRE_ELEM_LOC_REG;
699
7
    reg = reg_p ? sframe_fre->fp_reg : 0;
700
7
    deref_p = sframe_fre->fp_deref_p;
701
7
    reg_data = SFRAME_V3_FLEX_FDE_CTRLWORD_ENCODE (reg, deref_p, reg_p);
702
703
7
    offset_data = sframe_fre->fp_offset;
704
7
    dataword_func_map[idx].out_func (reg_data);
705
7
    dataword_func_map[idx].out_func (offset_data);
706
7
    fre_write_datawords += 2;
707
7
  }
708
21
    }
709
34
  else
710
34
    {
711
      /* SFrame FDE of type SFRAME_FDE_TYPE_DEFAULT.  */
712
      /* Output CFA related FRE data words.  */
713
34
      dataword_func_map[idx].out_func (sframe_fre->cfa_offset);
714
34
      fre_write_datawords++;
715
716
34
      if (sframe_ra_tracking_p ())
717
0
  {
718
0
    if (sframe_fre->ra_loc == SFRAME_FRE_ELEM_LOC_STACK)
719
0
      {
720
0
        dataword_func_map[idx].out_func (sframe_fre->ra_offset);
721
0
        fre_write_datawords++;
722
0
      }
723
    /* For s390x write padding RA offset, if FP without RA saved.  */
724
0
    else if (sframe_get_abi_arch () == SFRAME_ABI_S390X_ENDIAN_BIG
725
0
       && sframe_fre->fp_loc == SFRAME_FRE_ELEM_LOC_STACK)
726
0
      {
727
0
        dataword_func_map[idx].out_func (SFRAME_FRE_RA_OFFSET_INVALID);
728
0
        fre_write_datawords++;
729
0
      }
730
0
  }
731
34
      if (sframe_fre->fp_loc == SFRAME_FRE_ELEM_LOC_STACK)
732
3
  {
733
3
    dataword_func_map[idx].out_func (sframe_fre->fp_offset);
734
3
    fre_write_datawords++;
735
3
  }
736
34
    }
737
738
55
  return fre_write_datawords;
739
55
}
740
741
static void
742
output_sframe_row_entry (const struct sframe_func_entry *sframe_fde,
743
       const struct sframe_row_entry *sframe_fre)
744
55
{
745
55
  unsigned char fre_info;
746
55
  unsigned int fre_dataword_count;
747
55
  unsigned int fre_dataword_size;
748
55
  unsigned int fre_base_reg;
749
55
  bool fre_mangled_ra_p;
750
55
  expressionS exp;
751
55
  unsigned int fre_addr_size;
752
753
55
  unsigned int fre_write_datawords = 0;
754
55
  symbolS *fde_start_addr = get_dw_fde_start_addrS (sframe_fde->dw_fde);
755
55
  symbolS *fde_end_addr = get_dw_fde_end_addrS (sframe_fde->dw_fde);
756
55
  bool flex_p = sframe_fde->fde_flex_p;
757
758
55
  fre_addr_size = 4; /* 4 bytes by default.   FIXME tie it to fre_type? */
759
760
  /* SFrame FRE Start Address.  */
761
55
  if (SFRAME_FRE_TYPE_SELECTION_OPT)
762
55
    {
763
55
      create_fre_start_addr_exp (&exp, sframe_fre->pc_begin, fde_start_addr,
764
55
         fde_end_addr);
765
55
      frag_grow (fre_addr_size);
766
55
      frag_var (rs_sframe, fre_addr_size, 0, 0,
767
55
    make_expr_symbol (&exp), 0, (char *) frag_now);
768
55
    }
769
0
  else
770
0
    {
771
0
      gas_assert (fde_end_addr);
772
0
      exp = (expressionS) {
773
0
  .X_op = O_subtract,
774
0
  .X_add_symbol = sframe_fre->pc_begin, /* to.  */
775
0
  .X_op_symbol = fde_start_addr /* from.  */
776
0
      };
777
0
      emit_expr (&exp, fre_addr_size);
778
0
    }
779
780
  /* Create the fre_info using the CFA base register, number of data words and
781
     max size of a data word in this FRE.  Represent RA undefined as FRE
782
     without any data words and all FRE info word fields zeroed.  */
783
55
  if (sframe_fre->ra_undefined_p)
784
0
    {
785
0
      fre_base_reg = 0;
786
0
      fre_dataword_count = 0;
787
0
      fre_dataword_size = 0;
788
0
      fre_mangled_ra_p = 0;
789
0
    }
790
55
  else
791
55
    {
792
55
      fre_base_reg = get_fre_base_reg_id (sframe_fre);
793
55
      fre_dataword_count = get_fre_dataword_count (sframe_fre, flex_p);
794
55
      fre_dataword_size = sframe_get_fre_dataword_size (sframe_fre, flex_p);
795
55
      fre_mangled_ra_p = sframe_fre->mangled_ra_p;
796
55
    }
797
798
  /* Unused for flex FDE.  Set to zero.  */
799
55
  if (flex_p)
800
21
    fre_base_reg = 0;
801
802
55
  fre_info = sframe_set_fre_info (fre_base_reg, fre_dataword_count,
803
55
          fre_dataword_size, fre_mangled_ra_p);
804
55
  out_one (fre_info);
805
806
  /* Represent RA undefined as FRE without any data words.  */
807
55
  if (sframe_fre->ra_undefined_p)
808
0
    return;
809
810
55
  fre_write_datawords = output_sframe_row_entry_datawords (sframe_fde,
811
55
                 sframe_fre,
812
55
                 fre_dataword_size);
813
814
  /* Check if the expected number data words have been written out
815
     in this FRE.  */
816
55
  gas_assert (fre_write_datawords == fre_dataword_count);
817
55
}
818
819
static void
820
output_sframe_funcdesc_idx (symbolS *start_of_fre_section,
821
          symbolS *fre_symbol,
822
          const struct sframe_func_entry *sframe_fde)
823
27
{
824
27
  expressionS exp;
825
27
  symbolS *dw_fde_start_addrS, *dw_fde_end_addrS;
826
827
27
  dw_fde_start_addrS = get_dw_fde_start_addrS (sframe_fde->dw_fde);
828
27
  dw_fde_end_addrS = get_dw_fde_end_addrS (sframe_fde->dw_fde);
829
830
  /* Start address of the function.  gas always emits this value with encoding
831
     SFRAME_F_FDE_FUNC_START_PCREL.  See PR ld/32666.  */
832
27
  exp.X_op = O_subtract;
833
27
  exp.X_add_symbol = dw_fde_start_addrS; /* to location.  */
834
27
  exp.X_op_symbol = symbol_temp_new_now (); /* from location.  */
835
27
  exp.X_add_number = 0;
836
27
  emit_expr (&exp, sizeof_member (sframe_func_desc_idx,
837
27
          sfdi_func_start_offset));
838
839
  /* Size of the function in bytes.  */
840
27
  exp.X_op = O_subtract;
841
27
  exp.X_add_symbol = dw_fde_end_addrS;
842
27
  exp.X_op_symbol = dw_fde_start_addrS;
843
27
  exp.X_add_number = 0;
844
27
  emit_expr (&exp, sizeof_member (sframe_func_desc_idx,
845
27
          sfdi_func_size));
846
847
  /* Offset to the function data (attribtues, FREs) in the FRE subsection.  */
848
27
  exp.X_op = O_subtract;
849
27
  exp.X_add_symbol = fre_symbol; /* Minuend.  */
850
27
  exp.X_op_symbol = start_of_fre_section; /* Subtrahend.  */
851
27
  exp.X_add_number = 0;
852
27
  emit_expr (&exp, sizeof_member (sframe_func_desc_idx,
853
27
          sfdi_func_start_fre_off));
854
27
}
855
856
static void
857
output_sframe_func_desc_attr (const struct sframe_func_entry *sframe_fde)
858
27
{
859
27
  symbolS *dw_fde_start_addrS, *dw_fde_end_addrS;
860
27
  unsigned int pauth_key;
861
27
  bool signal_p;
862
863
27
  dw_fde_start_addrS = get_dw_fde_start_addrS (sframe_fde->dw_fde);
864
27
  dw_fde_end_addrS = get_dw_fde_end_addrS (sframe_fde->dw_fde);
865
866
  /* Number of FREs must fit uint16_t.  */
867
27
  gas_assert (sframe_fde->num_fres <= UINT16_MAX);
868
27
  out_two (sframe_fde->num_fres);
869
870
  /* SFrame FDE function info.  */
871
27
  unsigned char func_info;
872
27
  pauth_key = (get_dw_fde_pauth_b_key_p (sframe_fde->dw_fde)
873
27
         ? SFRAME_AARCH64_PAUTH_KEY_B : SFRAME_AARCH64_PAUTH_KEY_A);
874
27
  signal_p = get_dw_fde_signal_p (sframe_fde->dw_fde);
875
27
  func_info = sframe_set_func_info (SFRAME_V3_FDE_PCTYPE_INC,
876
27
            SFRAME_FRE_TYPE_ADDR4,
877
27
            pauth_key, signal_p);
878
27
  if (SFRAME_FRE_TYPE_SELECTION_OPT)
879
27
    {
880
27
      expressionS cexp;
881
27
      create_func_info_exp (&cexp, dw_fde_end_addrS, dw_fde_start_addrS,
882
27
          func_info);
883
27
      frag_grow (1); /* Size of func info is unsigned char.  */
884
27
      frag_var (rs_sframe, 1, 0, 0, make_expr_symbol (&cexp), 0,
885
27
    (char *) frag_now);
886
27
    }
887
0
  else
888
0
    out_one (func_info);
889
890
27
  uint8_t finfo2 = 0;
891
27
  if (sframe_fde->fde_flex_p)
892
11
    finfo2 = SFRAME_V3_SET_FDE_TYPE (finfo2, SFRAME_FDE_TYPE_FLEX);
893
27
  out_one (finfo2);
894
895
  /* Currently, GAS only emits SFrame FDE with PC Type
896
     SFRAME_V3_FDE_PCTYPE_INC.  Emit repetitive block size of 0.  */
897
27
  out_one (0);
898
27
}
899
900
static void
901
output_sframe_internal (void)
902
35
{
903
35
  expressionS exp;
904
35
  unsigned int i = 0;
905
906
35
  symbolS *end_of_frame_hdr;
907
35
  symbolS *end_of_frame_section;
908
35
  symbolS *start_of_func_desc_section;
909
35
  symbolS *start_of_fre_section;
910
35
  struct sframe_func_entry *sframe_fde, *sframe_fde_next;
911
35
  struct sframe_row_entry *sframe_fre;
912
35
  unsigned char abi_arch = 0;
913
35
  int fixed_fp_offset = SFRAME_CFA_FIXED_FP_INVALID;
914
35
  int fixed_ra_offset = SFRAME_CFA_FIXED_RA_INVALID;
915
916
  /* The function descriptor entries as dumped by the assembler are not
917
     sorted on PCs.  Fix for PR ld/32666 requires setting of an additional
918
     flag in SFrame Version 2.  */
919
35
  unsigned char sframe_flags = SFRAME_F_FDE_FUNC_START_PCREL;
920
921
35
  unsigned int num_fdes = get_num_sframe_fdes ();
922
35
  unsigned int num_fres = get_num_sframe_fres ();
923
35
  symbolS **fde_fre_symbols = XNEWVEC (symbolS *, num_fdes);
924
62
  for (i = 0; i < num_fdes; i++)
925
27
    fde_fre_symbols[i] = symbol_temp_make ();
926
927
35
  end_of_frame_hdr = symbol_temp_make ();
928
35
  start_of_fre_section = symbol_temp_make ();
929
35
  start_of_func_desc_section = symbol_temp_make ();
930
35
  end_of_frame_section = symbol_temp_make ();
931
932
  /* Output the preamble of SFrame section.  */
933
35
  out_two (SFRAME_MAGIC);
934
35
  out_one (SFRAME_VERSION);
935
  /* gas must ensure emitted SFrame sections have at least the required flags
936
     set.  */
937
35
  gas_assert ((sframe_flags & SFRAME_V2_GNU_AS_LD_ENCODING_FLAGS)
938
35
        == SFRAME_V2_GNU_AS_LD_ENCODING_FLAGS);
939
35
  out_one (sframe_flags);
940
  /* abi/arch.  */
941
35
#ifdef sframe_get_abi_arch
942
35
  abi_arch = sframe_get_abi_arch ();
943
35
#endif
944
35
  gas_assert (abi_arch);
945
35
  out_one (abi_arch);
946
947
  /* Offset for the FP register from CFA.  Neither of the AMD64 or AAPCS64
948
     ABIs have a fixed offset for the FP register from the CFA.  This may be
949
     useful in future (but not without additional support in the toolchain)
950
     for specialized handling/encoding for cases where, for example,
951
     -fno-omit-frame-pointer is used.  */
952
35
  out_one (fixed_fp_offset);
953
954
  /* All ABIs participating in SFrame generation must define
955
     sframe_ra_tracking_p.
956
     When RA tracking (in FREs) is not needed (e.g., AMD64), SFrame assumes
957
     the RA is going to be at a fixed offset from CFA.  Check that the fixed RA
958
     offset is appropriately defined in all cases.  */
959
35
  if (!sframe_ra_tracking_p ())
960
35
    {
961
35
      fixed_ra_offset = sframe_cfa_ra_offset ();
962
35
      gas_assert (fixed_ra_offset != SFRAME_CFA_FIXED_RA_INVALID);
963
35
    }
964
35
  out_one (fixed_ra_offset);
965
966
  /* None of the AMD64, AARCH64, or s390x ABIs need the auxiliary header.
967
     When the need does arise to use this field, the appropriate backend
968
     must provide this information.  */
969
35
  out_one (0); /* Auxiliary SFrame header length.  */
970
971
35
  out_four (num_fdes); /* Number of FDEs.  */
972
35
  out_four (num_fres); /* Number of FREs.  */
973
974
  /* Size of FRE sub-section.  */
975
35
  exp.X_op = O_subtract;
976
35
  exp.X_add_symbol = end_of_frame_section;
977
35
  exp.X_op_symbol = start_of_fre_section;
978
35
  exp.X_add_number = 0;
979
35
  emit_expr (&exp, sizeof_member (sframe_header, sfh_fre_len));
980
981
  /* Offset of FDE sub-section.  */
982
35
  exp.X_op = O_subtract;
983
35
  exp.X_add_symbol = end_of_frame_hdr;
984
35
  exp.X_op_symbol = start_of_func_desc_section;
985
35
  exp.X_add_number = 0;
986
35
  emit_expr (&exp, sizeof_member (sframe_header, sfh_fdeoff));
987
988
  /* Offset of FRE sub-section.  */
989
35
  exp.X_op = O_subtract;
990
35
  exp.X_add_symbol = start_of_fre_section;
991
35
  exp.X_op_symbol = end_of_frame_hdr;
992
35
  exp.X_add_number = 0;
993
35
  emit_expr (&exp, sizeof_member (sframe_header, sfh_freoff));
994
995
35
  symbol_set_value_now (end_of_frame_hdr);
996
35
  symbol_set_value_now (start_of_func_desc_section);
997
998
  /* Output the SFrame function descriptor entries.  */
999
35
  i = 0;
1000
62
  for (sframe_fde = all_sframe_fdes; sframe_fde; sframe_fde = sframe_fde->next)
1001
27
    {
1002
27
      output_sframe_funcdesc_idx (start_of_fre_section, fde_fre_symbols[i],
1003
27
          sframe_fde);
1004
27
      i++;
1005
27
    }
1006
1007
35
  symbol_set_value_now (start_of_fre_section);
1008
1009
  /* Output the SFrame FREs.  */
1010
35
  i = 0;
1011
35
  sframe_fde = all_sframe_fdes;
1012
1013
62
  for (sframe_fde = all_sframe_fdes; sframe_fde; sframe_fde = sframe_fde_next)
1014
27
    {
1015
27
      symbol_set_value_now (fde_fre_symbols[i]);
1016
1017
27
      output_sframe_func_desc_attr (sframe_fde);
1018
1019
27
      for (sframe_fre = sframe_fde->sframe_fres;
1020
82
     sframe_fre;
1021
55
     sframe_fre = sframe_fre->next)
1022
55
  {
1023
55
    output_sframe_row_entry (sframe_fde, sframe_fre);
1024
55
  }
1025
27
      i++;
1026
27
      sframe_fde_next = sframe_fde->next;
1027
27
      sframe_fde_free (sframe_fde);
1028
27
    }
1029
35
  all_sframe_fdes = NULL;
1030
35
  last_sframe_fde = &all_sframe_fdes;
1031
1032
35
  symbol_set_value_now (end_of_frame_section);
1033
1034
35
  gas_assert (i == num_fdes);
1035
1036
35
  free (fde_fre_symbols);
1037
35
  fde_fre_symbols = NULL;
1038
35
}
1039
1040
static unsigned int
1041
get_num_sframe_fdes (void)
1042
35
{
1043
35
  struct sframe_func_entry *sframe_fde;
1044
35
  unsigned int total_fdes = 0;
1045
1046
62
  for (sframe_fde = all_sframe_fdes; sframe_fde ; sframe_fde = sframe_fde->next)
1047
27
    total_fdes++;
1048
1049
35
  return total_fdes;
1050
35
}
1051
1052
/* Get the total number of SFrame row entries across the FDEs.  */
1053
1054
static unsigned int
1055
get_num_sframe_fres (void)
1056
35
{
1057
35
  struct sframe_func_entry *sframe_fde;
1058
35
  unsigned int total_fres = 0;
1059
1060
62
  for (sframe_fde = all_sframe_fdes; sframe_fde ; sframe_fde = sframe_fde->next)
1061
27
    total_fres += sframe_fde->num_fres;
1062
1063
35
  return total_fres;
1064
35
}
1065
1066
/* SFrame translation context functions.  */
1067
1068
/* Allocate a new SFrame translation context.  */
1069
1070
static struct sframe_xlate_ctx*
1071
sframe_xlate_ctx_alloc (void)
1072
35
{
1073
35
  struct sframe_xlate_ctx* xlate_ctx = XCNEW (struct sframe_xlate_ctx);
1074
35
  return xlate_ctx;
1075
35
}
1076
1077
/* Initialize the given SFrame translation context.  */
1078
1079
static void
1080
sframe_xlate_ctx_init (struct sframe_xlate_ctx *xlate_ctx)
1081
37
{
1082
37
  xlate_ctx->dw_fde = NULL;
1083
37
  xlate_ctx->flex_p = false;
1084
37
  xlate_ctx->first_fre = NULL;
1085
37
  xlate_ctx->last_fre = NULL;
1086
37
  xlate_ctx->cur_fre = NULL;
1087
37
  xlate_ctx->remember_fre = NULL;
1088
37
  xlate_ctx->num_xlate_fres = 0;
1089
37
}
1090
1091
/* Cleanup the given SFrame translation context.  */
1092
1093
static void
1094
sframe_xlate_ctx_cleanup (struct sframe_xlate_ctx *xlate_ctx)
1095
10
{
1096
10
  sframe_row_entry_free (xlate_ctx->first_fre);
1097
10
  XDELETE (xlate_ctx->remember_fre);
1098
10
  xlate_ctx->remember_fre = NULL;
1099
10
  XDELETE (xlate_ctx->cur_fre);
1100
10
  xlate_ctx->cur_fre = NULL;
1101
10
}
1102
1103
/* Transfer the state from the SFrame translation context to the SFrame FDE.  */
1104
1105
static void
1106
sframe_xlate_ctx_finalize (struct sframe_xlate_ctx *xlate_ctx,
1107
         struct sframe_func_entry *sframe_fde)
1108
27
{
1109
27
  sframe_fde->dw_fde = xlate_ctx->dw_fde;
1110
27
  sframe_fde->fde_flex_p = xlate_ctx->flex_p;
1111
27
  sframe_fde->sframe_fres = xlate_ctx->first_fre;
1112
27
  sframe_fde->num_fres = xlate_ctx->num_xlate_fres;
1113
  /* remember_fre is cloned copy of the applicable fre (where necessary).
1114
     Since this is not included in the list of sframe_fres, free it.  */
1115
27
  XDELETE (xlate_ctx->remember_fre);
1116
27
  xlate_ctx->remember_fre = NULL;
1117
27
}
1118
1119
/* Get the current CFA base register from the scratchpad FRE (cur_fre).
1120
   NB: this may return a value of SFRAME_FRE_REG_INVALID.  */
1121
1122
static unsigned int
1123
sframe_xlate_ctx_get_cur_cfa_reg (const struct sframe_xlate_ctx *xlate_ctx)
1124
10
{
1125
10
  gas_assert (xlate_ctx && xlate_ctx->cur_fre);
1126
1127
10
  return xlate_ctx->cur_fre->cfa_base_reg;
1128
10
}
1129
1130
/* Add the given FRE in the list of frame row entries in the given FDE
1131
   translation context.  */
1132
1133
static void
1134
sframe_xlate_ctx_add_fre (struct sframe_xlate_ctx *xlate_ctx,
1135
        struct sframe_row_entry *fre)
1136
62
{
1137
62
  gas_assert (xlate_ctx && fre);
1138
1139
  /* Add the frame row entry.  */
1140
62
  if (!xlate_ctx->first_fre)
1141
33
    xlate_ctx->first_fre = fre;
1142
29
  else if (xlate_ctx->last_fre)
1143
29
    xlate_ctx->last_fre->next = fre;
1144
1145
62
  xlate_ctx->last_fre = fre;
1146
1147
  /* Keep track of the total number of SFrame frame row entries.  */
1148
62
  xlate_ctx->num_xlate_fres++;
1149
62
}
1150
1151
/* A SFrame Frame Row Entry is self-sufficient in terms of stack tracing info
1152
   for a given PC.  It contains information assimilated from multiple CFI
1153
   instructions, and hence, a new SFrame FRE is initialized with the data from
1154
   the previous known FRE, if any.
1155
1156
   Understandably, not all information (especially the instruction begin
1157
   and end boundaries) needs to be relayed.  Hence, the caller of this API
1158
   must set the pc_begin and pc_end as applicable.  */
1159
1160
static void
1161
sframe_row_entry_initialize (struct sframe_row_entry *cur_fre,
1162
           const struct sframe_row_entry *prev_fre)
1163
35
{
1164
35
  gas_assert (prev_fre);
1165
35
  cur_fre->cfa_base_reg = prev_fre->cfa_base_reg;
1166
35
  cur_fre->cfa_offset = prev_fre->cfa_offset;
1167
35
  cur_fre->cfa_deref_p = prev_fre->cfa_deref_p;
1168
35
  cur_fre->fp_loc = prev_fre->fp_loc;
1169
35
  cur_fre->fp_reg = prev_fre->fp_reg;
1170
35
  cur_fre->fp_offset = prev_fre->fp_offset;
1171
35
  cur_fre->fp_deref_p = prev_fre->fp_deref_p;
1172
35
  cur_fre->ra_loc = prev_fre->ra_loc;
1173
35
  cur_fre->ra_reg = prev_fre->ra_reg;
1174
35
  cur_fre->ra_offset = prev_fre->ra_offset;
1175
35
  cur_fre->ra_deref_p = prev_fre->ra_deref_p;
1176
  /* Treat RA mangling as a sticky bit.  It retains its value until another
1177
     .cfi_negate_ra_state is seen.  */
1178
35
  cur_fre->mangled_ra_p = prev_fre->mangled_ra_p;
1179
  /* Treat RA undefined as a sticky bit.  It retains its value until a
1180
     .cfi_offset RA, .cfi_register RA, .cfi_restore RA, or .cfi_same_value RA
1181
     is seen.  */
1182
35
  cur_fre->ra_undefined_p = prev_fre->ra_undefined_p;
1183
35
}
1184
1185
/* Return SFrame register name for SP, FP, and RA, or NULL if other.  */
1186
1187
static const char *
1188
sframe_register_name (unsigned int reg)
1189
1
{
1190
1
  if (reg == SFRAME_CFA_SP_REG)
1191
0
    return "SP";
1192
1
  else if (reg == SFRAME_CFA_FP_REG)
1193
1
    return "FP";
1194
0
  else if (reg == SFRAME_CFA_RA_REG)
1195
0
    return "RA";
1196
0
  else
1197
0
    return NULL;
1198
1
}
1199
1200
/* Translate DW_CFA_advance_loc into SFrame context.
1201
   Return SFRAME_XLATE_OK if success.  */
1202
1203
static int
1204
sframe_xlate_do_advance_loc (struct sframe_xlate_ctx *xlate_ctx,
1205
           const struct cfi_insn_data *cfi_insn)
1206
47
{
1207
47
  struct sframe_row_entry *last_fre = xlate_ctx->last_fre;
1208
  /* Get the scratchpad FRE currently being updated as the cfi_insn's
1209
     get interpreted.  This FRE eventually gets linked in into the
1210
     list of FREs for the specific function.  */
1211
47
  struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
1212
1213
47
  if (cur_fre)
1214
47
    {
1215
47
      if (!cur_fre->merge_candidate)
1216
35
  {
1217
35
    sframe_fre_set_end_addr (cur_fre, cfi_insn->u.ll.lab2);
1218
1219
35
    sframe_xlate_ctx_add_fre (xlate_ctx, cur_fre);
1220
35
    last_fre = xlate_ctx->last_fre;
1221
1222
35
    xlate_ctx->cur_fre = sframe_row_entry_new ();
1223
35
    cur_fre = xlate_ctx->cur_fre;
1224
1225
35
    if (last_fre)
1226
35
      sframe_row_entry_initialize (cur_fre, last_fre);
1227
35
  }
1228
12
      else
1229
12
  {
1230
12
    sframe_fre_set_end_addr (last_fre, cfi_insn->u.ll.lab2);
1231
12
    gas_assert (last_fre->merge_candidate == false);
1232
12
  }
1233
47
    }
1234
0
  else
1235
0
    {
1236
0
      xlate_ctx->cur_fre = sframe_row_entry_new ();
1237
0
      cur_fre = xlate_ctx->cur_fre;
1238
0
    }
1239
1240
47
  gas_assert (cur_fre);
1241
47
  sframe_fre_set_begin_addr (cur_fre, cfi_insn->u.ll.lab2);
1242
1243
47
  return SFRAME_XLATE_OK;
1244
47
}
1245
1246
/* Translate DW_CFA_def_cfa into SFrame context.
1247
   Return SFRAME_XLATE_OK if success.  */
1248
1249
static int
1250
sframe_xlate_do_def_cfa (struct sframe_xlate_ctx *xlate_ctx,
1251
       const struct cfi_insn_data *cfi_insn)
1252
1253
55
{
1254
  /* Get the scratchpad FRE.  This FRE will eventually get linked in.  */
1255
55
  struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
1256
55
  if (!cur_fre)
1257
37
  {
1258
37
    xlate_ctx->cur_fre = sframe_row_entry_new ();
1259
37
    cur_fre = xlate_ctx->cur_fre;
1260
37
    sframe_fre_set_begin_addr (cur_fre,
1261
37
             get_dw_fde_start_addrS (xlate_ctx->dw_fde));
1262
37
  }
1263
1264
55
  offsetT offset = cfi_insn->u.ri.offset;
1265
55
  bool bound_p = sframe_fre_stack_offset_bound_p (offset, true);
1266
55
  if (!bound_p)
1267
1
    {
1268
1
      as_warn (_("no SFrame FDE emitted; "
1269
1
     ".cfi_def_cfa with unsupported offset value"));
1270
1
      return SFRAME_XLATE_ERR_NOTREPRESENTED;
1271
1
    }
1272
1273
  /* Define the current CFA rule to use the provided register and
1274
     offset.  Typically, the CFA rule uses SP/FP based CFA.  However, with
1275
     SFrame V3 specification, if the CFA register is not FP/SP, SFrame FDE type
1276
     SFRAME_FDE_TYPE_FLEX type may be used.
1277
1278
     GAS uses the hook sframe_support_flex_fde_p () to determine if SFrame FDE
1279
     of type SFRAME_FDE_TYPE_FLEX can be emitted for the specific target.
1280
     Non-SP/FP based CFA may be seen for:
1281
       - AMD64 (e.g., DRAP, stack alignment), or
1282
       - s390x, where this may be seen for (GCC) generated code for static stack
1283
         clash protection.  */
1284
54
  if (cfi_insn->u.ri.reg != SFRAME_CFA_SP_REG
1285
17
      && cfi_insn->u.ri.reg != SFRAME_CFA_FP_REG)
1286
17
    {
1287
17
      if (!sframe_support_flex_fde_p ())
1288
0
  {
1289
0
    as_warn (_("no SFrame FDE emitted; "
1290
0
         "non-SP/FP register %u in .cfi_def_cfa"),
1291
0
       cfi_insn->u.ri.reg);
1292
0
    return SFRAME_XLATE_ERR_NOTREPRESENTED;
1293
0
  }
1294
17
      else
1295
17
  xlate_ctx->flex_p = true;
1296
17
    }
1297
1298
54
  sframe_fre_set_cfa_base_reg (cur_fre, cfi_insn->u.ri.reg);
1299
54
  sframe_fre_set_cfa_offset (cur_fre, cfi_insn->u.ri.offset);
1300
54
  cur_fre->merge_candidate = false;
1301
54
  cur_fre->cfa_deref_p = false;
1302
1303
54
  return SFRAME_XLATE_OK;
1304
54
}
1305
1306
/* Translate DW_CFA_def_cfa_register into SFrame context.
1307
   Return SFRAME_XLATE_OK if success.  */
1308
1309
static int
1310
sframe_xlate_do_def_cfa_register (struct sframe_xlate_ctx *xlate_ctx,
1311
          const struct cfi_insn_data *cfi_insn)
1312
13
{
1313
13
  const struct sframe_row_entry *last_fre = xlate_ctx->last_fre;
1314
  /* Get the scratchpad FRE.  This FRE will eventually get linked in.  */
1315
13
  struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
1316
1317
13
  gas_assert (cur_fre);
1318
  /* Define the current CFA rule to use the provided register (but to
1319
     keep the old offset).  However, if the register is not FP/SP,
1320
     skip creating SFrame stack trace info for the function.  */
1321
13
  if (cfi_insn->u.r != SFRAME_CFA_SP_REG
1322
13
      && cfi_insn->u.r != SFRAME_CFA_FP_REG)
1323
4
    {
1324
4
      if (!sframe_support_flex_fde_p ())
1325
0
  {
1326
0
    as_warn (_("no SFrame FDE emitted; "
1327
0
         "non-SP/FP register %u in .cfi_def_cfa_register"),
1328
0
       cfi_insn->u.ri.reg);
1329
0
    return SFRAME_XLATE_ERR_NOTREPRESENTED;
1330
0
  }
1331
4
      else
1332
  /* Currently, SFRAME_FDE_TYPE_FLEX is generated for AMD64 only.  */
1333
4
  xlate_ctx->flex_p = true;
1334
4
    }
1335
1336
13
  sframe_fre_set_cfa_base_reg (cur_fre, cfi_insn->u.r);
1337
13
  if (last_fre)
1338
12
    sframe_fre_set_cfa_offset (cur_fre, sframe_fre_get_cfa_offset (last_fre));
1339
13
  cur_fre->cfa_deref_p = false;
1340
1341
13
  cur_fre->merge_candidate = false;
1342
1343
13
  return SFRAME_XLATE_OK;
1344
13
}
1345
1346
/* Translate DW_CFA_def_cfa_offset into SFrame context.
1347
   Return SFRAME_XLATE_OK if success.  */
1348
1349
static int
1350
sframe_xlate_do_def_cfa_offset (struct sframe_xlate_ctx *xlate_ctx,
1351
        const struct cfi_insn_data *cfi_insn)
1352
10
{
1353
  /* The scratchpad FRE currently being updated with each cfi_insn
1354
     being interpreted.  This FRE eventually gets linked in into the
1355
     list of FREs for the specific function.  */
1356
10
  struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
1357
10
  unsigned int cur_cfa_reg = sframe_xlate_ctx_get_cur_cfa_reg (xlate_ctx);
1358
1359
10
  gas_assert (cur_fre);
1360
  /*  Define the current CFA rule to use the provided offset (but to keep
1361
      the old register).  However, if the old register is not FP/SP,
1362
      skip creating SFrame stack trace info for the function.  */
1363
10
  if (cur_cfa_reg == SFRAME_CFA_FP_REG || cur_cfa_reg == SFRAME_CFA_SP_REG)
1364
9
    {
1365
9
      if (sframe_fre_stack_offset_bound_p (cfi_insn->u.i, true))
1366
8
  {
1367
8
    sframe_fre_set_cfa_offset (cur_fre, cfi_insn->u.i);
1368
8
    cur_fre->merge_candidate = false;
1369
8
  }
1370
1
      else
1371
1
  {
1372
1
    as_warn (_("no SFrame FDE emitted; "
1373
1
         ".cfi_def_cfa_offset with unsupported offset value"));
1374
1
    return SFRAME_XLATE_ERR_NOTREPRESENTED;
1375
1
  }
1376
9
    }
1377
1
  else
1378
1
    {
1379
      /* No CFA base register in effect.  Non-SP/FP CFA base register should
1380
   not occur, as sframe_xlate_do_def_cfa[_register] would detect this.  */
1381
1
      as_warn (_("no SFrame FDE emitted; "
1382
1
     ".cfi_def_cfa_offset without CFA base register in effect"));
1383
1
      return SFRAME_XLATE_ERR_NOTREPRESENTED;
1384
1
    }
1385
1386
8
  return SFRAME_XLATE_OK;
1387
10
}
1388
1389
/* Translate DW_CFA_offset into SFrame context.
1390
   Return SFRAME_XLATE_OK if success.  */
1391
1392
static int
1393
sframe_xlate_do_offset (struct sframe_xlate_ctx *xlate_ctx,
1394
      const struct cfi_insn_data *cfi_insn)
1395
60
{
1396
  /* The scratchpad FRE currently being updated with each cfi_insn
1397
     being interpreted.  This FRE eventually gets linked in into the
1398
     list of FREs for the specific function.  */
1399
60
  struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
1400
60
  gas_assert (cur_fre);
1401
1402
  /* For ABIs not tracking RA, the return address is expected to be in a
1403
     specific location.  Explicit manourvering to a different offset (than the
1404
     default offset) is non-representable in SFrame, unless flex FDE generation
1405
     is supported for the ABI.  */
1406
60
  if (!sframe_support_flex_fde_p () && !sframe_ra_tracking_p ()
1407
0
      && cfi_insn->u.ri.reg == SFRAME_CFA_RA_REG
1408
0
      && cfi_insn->u.ri.offset != sframe_cfa_ra_offset ())
1409
0
    {
1410
0
      as_warn (_("no SFrame FDE emitted; %s register %u in .cfi_offset"),
1411
0
         sframe_register_name (cfi_insn->u.ri.reg), cfi_insn->u.ri.reg);
1412
0
      return SFRAME_XLATE_ERR_NOTREPRESENTED;  /* Not represented.  */
1413
0
    }
1414
1415
  /* Change the rule for the register indicated by the register number to
1416
     be the specified offset.  */
1417
  /* Ignore SP reg, as it can be recovered from the CFA tracking info.  */
1418
60
  if (cfi_insn->u.ri.reg == SFRAME_CFA_FP_REG)
1419
8
    {
1420
8
      sframe_fre_set_fp_track (cur_fre, cfi_insn->u.ri.offset);
1421
8
      cur_fre->fp_reg = SFRAME_FRE_REG_INVALID;
1422
8
      cur_fre->fp_deref_p = true;
1423
8
      cur_fre->merge_candidate = false;
1424
8
    }
1425
  /* Either the ABI has enabled RA tracking, in which case we must process the
1426
     DW_CFA_offset opcode for REG_RA like usual.  Or if the ABI has not enabled
1427
     RA tracking, but flex FDE generation is supported, distinguish between
1428
     whether its time to reset the RA tracking state or not.  */
1429
52
  else if (cfi_insn->u.ri.reg == SFRAME_CFA_RA_REG)
1430
41
    {
1431
41
      if (!sframe_ra_tracking_p ()
1432
41
    && cfi_insn->u.ri.offset == sframe_cfa_ra_offset ())
1433
37
  {
1434
    /* Reset RA tracking info, if fixed offset.  */
1435
37
    cur_fre->ra_reg = SFRAME_FRE_REG_INVALID;
1436
37
    cur_fre->ra_loc = SFRAME_FRE_ELEM_LOC_NONE;
1437
37
    cur_fre->ra_deref_p = false;
1438
37
    cur_fre->merge_candidate = false;
1439
37
  }
1440
4
      else
1441
4
  {
1442
4
    sframe_fre_set_ra_track (cur_fre, cfi_insn->u.ri.offset);
1443
4
    cur_fre->ra_reg = SFRAME_FRE_REG_INVALID;
1444
4
    cur_fre->ra_loc = SFRAME_FRE_ELEM_LOC_STACK;
1445
4
    cur_fre->ra_deref_p = true;
1446
4
    cur_fre->merge_candidate = false;
1447
1448
4
    if (!sframe_ra_tracking_p () && sframe_support_flex_fde_p ())
1449
4
      xlate_ctx->flex_p = true;
1450
4
  }
1451
41
    }
1452
1453
  /* Skip all other registers.  */
1454
60
  return SFRAME_XLATE_OK;
1455
60
}
1456
1457
/* Translate DW_CFA_val_offset into SFrame context.
1458
   Return SFRAME_XLATE_OK if success.
1459
1460
   When CFI_ESC_P is true, the CFI_INSN is hand-crafted using CFI_escape
1461
   data.  See sframe_xlate_do_escape_val_offset.  */
1462
1463
static int
1464
sframe_xlate_do_val_offset (const struct sframe_xlate_ctx *xlate_ctx ATTRIBUTE_UNUSED,
1465
          const struct cfi_insn_data *cfi_insn,
1466
          bool cfi_esc_p)
1467
9
{
1468
  /* Previous value of register is CFA + offset.  However, if the specified
1469
     register is not interesting (SP, FP, or RA reg), the current
1470
     DW_CFA_val_offset instruction can be safely skipped without sacrificing
1471
     the asynchronicity of stack trace information.  */
1472
9
  if (cfi_insn->u.ri.reg == SFRAME_CFA_FP_REG
1473
8
      || (sframe_ra_tracking_p () && cfi_insn->u.ri.reg == SFRAME_CFA_RA_REG)
1474
      /* Ignore SP reg, if offset matches assumed default rule.  */
1475
8
      || (cfi_insn->u.ri.reg == SFRAME_CFA_SP_REG
1476
4
    && ((sframe_get_abi_arch () != SFRAME_ABI_S390X_ENDIAN_BIG
1477
4
         && cfi_insn->u.ri.offset != 0)
1478
4
        || (sframe_get_abi_arch () == SFRAME_ABI_S390X_ENDIAN_BIG
1479
0
      && cfi_insn->u.ri.offset != SFRAME_S390X_SP_VAL_OFFSET))))
1480
1
    {
1481
1
      as_warn (_("no SFrame FDE emitted; %s with %s reg %u"),
1482
1
         cfi_esc_p ? ".cfi_escape DW_CFA_val_offset" : ".cfi_val_offset",
1483
1
         sframe_register_name (cfi_insn->u.ri.reg), cfi_insn->u.ri.reg);
1484
1
      return SFRAME_XLATE_ERR_NOTREPRESENTED; /* Not represented.  */
1485
1
    }
1486
1487
  /* Safe to skip.  */
1488
8
  return SFRAME_XLATE_OK;
1489
9
}
1490
1491
/* Translate DW_CFA_register into SFrame context.
1492
1493
   This opcode indicates: Previous value of register1 is register2.  This is
1494
   not representable using FDE type SFRAME_FDE_TYPE_DEFAULT.  Hence, if
1495
   flexible FDE is not enabled for the ABI/arch, detect the use of registers
1496
   interesting to SFrame (FP, RA for this opcode), and skip FDE generation
1497
   while warning the user.  Same applies for SP, except that it needs special
1498
   handling for s390.
1499
1500
   Return SFRAME_XLATE_OK if success.  */
1501
1502
static int
1503
sframe_xlate_do_register (struct sframe_xlate_ctx *xlate_ctx,
1504
        const struct cfi_insn_data *cfi_insn)
1505
22
{
1506
22
  if (sframe_support_flex_fde_p ())
1507
22
    {
1508
22
      struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
1509
1510
22
      if (cfi_insn->u.rr.reg1 == SFRAME_CFA_FP_REG)
1511
0
  {
1512
0
    sframe_fre_set_fp_track (cur_fre, 0);
1513
0
    cur_fre->fp_loc = SFRAME_FRE_ELEM_LOC_REG;
1514
0
    cur_fre->fp_reg = cfi_insn->u.rr.reg2;
1515
0
    cur_fre->fp_deref_p = false;
1516
0
    cur_fre->merge_candidate = false;
1517
0
    xlate_ctx->flex_p = true;
1518
0
    return SFRAME_XLATE_OK;
1519
0
  }
1520
22
      else if (cfi_insn->u.rr.reg1 == SFRAME_CFA_RA_REG)
1521
0
  {
1522
0
    sframe_fre_set_ra_track (cur_fre, 0);
1523
0
    cur_fre->ra_loc = SFRAME_FRE_ELEM_LOC_REG;
1524
0
    cur_fre->ra_reg = cfi_insn->u.rr.reg2;
1525
0
    cur_fre->ra_deref_p = false;
1526
0
    cur_fre->merge_candidate = false;
1527
0
    xlate_ctx->flex_p = true;
1528
0
    return SFRAME_XLATE_OK;
1529
0
  }
1530
      /* Recovering REG_SP from an alternate register is not represented in
1531
   SFrame.  Fallthrough if SFRAME_CFA_SP_REG and error out.  */
1532
22
    }
1533
1534
22
  if (cfi_insn->u.rr.reg1 == SFRAME_CFA_RA_REG
1535
      /* SFrame does not track SP explicitly.  */
1536
22
      || (cfi_insn->u.rr.reg1 == SFRAME_CFA_SP_REG
1537
0
    && sframe_get_abi_arch () != SFRAME_ABI_S390X_ENDIAN_BIG)
1538
22
      || cfi_insn->u.rr.reg1 == SFRAME_CFA_FP_REG)
1539
0
    {
1540
0
      as_warn (_("no SFrame FDE emitted; %s register %u in .cfi_register"),
1541
0
         sframe_register_name (cfi_insn->u.rr.reg1), cfi_insn->u.rr.reg1);
1542
0
      return SFRAME_XLATE_ERR_NOTREPRESENTED;  /* Not represented.  */
1543
0
    }
1544
1545
  /* Safe to skip.  */
1546
22
  return SFRAME_XLATE_OK;
1547
22
}
1548
1549
/* Translate DW_CFA_remember_state into SFrame context.
1550
   Return SFRAME_XLATE_OK if success.  */
1551
1552
static int
1553
sframe_xlate_do_remember_state (struct sframe_xlate_ctx *xlate_ctx)
1554
0
{
1555
0
  const struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
1556
1557
  /* If there is no FRE state to remember, nothing to do here.  Return
1558
     early with non-zero error code, this will cause no SFrame stack trace
1559
     info for the function involved.  */
1560
0
  if (!cur_fre)
1561
0
    {
1562
0
      as_warn (_("no SFrame FDE emitted; "
1563
0
     ".cfi_remember_state without prior SFrame FRE state"));
1564
0
      return SFRAME_XLATE_ERR_INVAL;
1565
0
    }
1566
1567
0
  if (!xlate_ctx->remember_fre)
1568
0
    xlate_ctx->remember_fre = sframe_row_entry_new ();
1569
0
  sframe_row_entry_initialize (xlate_ctx->remember_fre, cur_fre);
1570
1571
0
  return SFRAME_XLATE_OK;
1572
0
}
1573
1574
/* Translate DW_CFA_restore_state into SFrame context.
1575
   Return SFRAME_XLATE_OK if success.  */
1576
1577
static int
1578
sframe_xlate_do_restore_state (struct sframe_xlate_ctx *xlate_ctx)
1579
0
{
1580
  /* The scratchpad FRE currently being updated with each cfi_insn
1581
     being interpreted.  This FRE eventually gets linked in into the
1582
     list of FREs for the specific function.  */
1583
0
  struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
1584
1585
0
  gas_assert (xlate_ctx->remember_fre);
1586
0
  gas_assert (cur_fre && cur_fre->merge_candidate);
1587
1588
  /* Get the CFA state from the DW_CFA_remember_state insn.  */
1589
0
  sframe_row_entry_initialize (cur_fre, xlate_ctx->remember_fre);
1590
  /* The PC boundaries of the current SFrame FRE are updated
1591
     via other machinery.  */
1592
0
  cur_fre->merge_candidate = false;
1593
0
  return SFRAME_XLATE_OK;
1594
0
}
1595
1596
/* Translate DW_CFA_restore into SFrame context.
1597
   Return SFRAME_XLATE_OK if success.  */
1598
1599
static int
1600
sframe_xlate_do_restore (struct sframe_xlate_ctx *xlate_ctx,
1601
       const struct cfi_insn_data *cfi_insn)
1602
11
{
1603
11
  struct sframe_row_entry *cie_fre = xlate_ctx->first_fre;
1604
  /* The scratchpad FRE currently being updated with each cfi_insn
1605
     being interpreted.  This FRE eventually gets linked in into the
1606
     list of FREs for the specific function.  */
1607
11
  struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
1608
1609
  /* PR gas/33170.  It is valid to have a:
1610
       .cfi_restore N
1611
    even at the entry of a function; in which case cie_fre is not yet setup.
1612
    Point cie_fre to cur_fre, and let the machinery proceed to update
1613
    merge_candidate as usual.  */
1614
11
  if (cie_fre == NULL)
1615
0
    cie_fre = cur_fre;
1616
1617
  /* Change the rule for the indicated register to the rule assigned to
1618
     it by the initial_instructions in the CIE.  SFrame FREs track only CFA
1619
     and FP / RA for backtracing purposes; skip the other .cfi_restore
1620
     directives.  */
1621
11
  if (cfi_insn->u.r == SFRAME_CFA_FP_REG)
1622
1
    {
1623
1
      gas_assert (cur_fre);
1624
1
      cur_fre->fp_loc = cie_fre->fp_loc;
1625
1
      cur_fre->fp_offset = cie_fre->fp_offset;
1626
1
      cur_fre->merge_candidate = false;
1627
1
    }
1628
10
  else if (sframe_ra_tracking_p ()
1629
0
     && cfi_insn->u.r == SFRAME_CFA_RA_REG)
1630
0
    {
1631
0
      gas_assert (cur_fre);
1632
0
      cur_fre->ra_loc = cie_fre->ra_loc;
1633
0
      cur_fre->ra_offset = cie_fre->ra_offset;
1634
0
      cur_fre->ra_undefined_p = cie_fre->ra_undefined_p;
1635
0
      cur_fre->merge_candidate = false;
1636
0
    }
1637
11
  return SFRAME_XLATE_OK;
1638
11
}
1639
1640
/* Translate DW_CFA_AARCH64_negate_ra_state into SFrame context.
1641
   Return SFRAME_XLATE_OK if success.  */
1642
1643
static int
1644
sframe_xlate_do_aarch64_negate_ra_state (struct sframe_xlate_ctx *xlate_ctx,
1645
           const struct cfi_insn_data *cfi_insn ATTRIBUTE_UNUSED)
1646
0
{
1647
0
  struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
1648
1649
0
  gas_assert (cur_fre);
1650
  /* Toggle the mangled RA status bit.  */
1651
0
  cur_fre->mangled_ra_p = !cur_fre->mangled_ra_p;
1652
0
  cur_fre->merge_candidate = false;
1653
1654
0
  return SFRAME_XLATE_OK;
1655
0
}
1656
1657
/* Translate DW_CFA_AARCH64_negate_ra_state_with_pc into SFrame context.
1658
   Return SFRAME_XLATE_OK if success.  */
1659
1660
static int
1661
sframe_xlate_do_aarch64_negate_ra_state_with_pc (struct sframe_xlate_ctx *xlate_ctx ATTRIBUTE_UNUSED,
1662
             const struct cfi_insn_data *cfi_insn ATTRIBUTE_UNUSED)
1663
0
{
1664
0
  as_warn (_("no SFrame FDE emitted; .cfi_negate_ra_state_with_pc"));
1665
  /* The used signing method should be encoded inside the FDE in SFrame v3.
1666
     For now, PAuth_LR extension is not supported with SFrame.  */
1667
0
  return SFRAME_XLATE_ERR_NOTREPRESENTED;  /* Not represented.  */
1668
0
}
1669
1670
/* Translate DW_CFA_GNU_window_save into SFrame context.
1671
   DW_CFA_GNU_window_save is a DWARF Sparc extension, but is multiplexed with a
1672
   directive of DWARF AArch64 extension: DW_CFA_AARCH64_negate_ra_state.
1673
   The AArch64 backend of GCC 14 and older versions was emitting mistakenly the
1674
   Sparc CFI directive (.cfi_window_save).  From GCC 15, the AArch64 backend
1675
   only emits .cfi_negate_ra_state.  For backward compatibility, the handler for
1676
   .cfi_window_save needs to check whether the directive was used in a AArch64
1677
   ABI context or not.
1678
   Return SFRAME_XLATE_OK if success.  */
1679
1680
static int
1681
sframe_xlate_do_gnu_window_save (struct sframe_xlate_ctx *xlate_ctx,
1682
         const struct cfi_insn_data *cfi_insn)
1683
0
{
1684
0
  unsigned char abi_arch = sframe_get_abi_arch ();
1685
1686
  /* Translate DW_CFA_AARCH64_negate_ra_state into SFrame context.  */
1687
0
  if (abi_arch == SFRAME_ABI_AARCH64_ENDIAN_BIG
1688
0
      || abi_arch == SFRAME_ABI_AARCH64_ENDIAN_LITTLE)
1689
0
    return sframe_xlate_do_aarch64_negate_ra_state (xlate_ctx, cfi_insn);
1690
1691
0
  as_warn (_("no SFrame FDE emitted; .cfi_window_save"));
1692
0
  return SFRAME_XLATE_ERR_NOTREPRESENTED;  /* Not represented.  */
1693
0
}
1694
1695
/* Translate a DWARF sleb128 offset in the CFI escape data E to an offsetT.
1696
   Update the value in OFFSET if success (and return SFRAME_XLATE_OK).
1697
   Return SFRAME_XLATE_ERR_INVAL if error.  */
1698
1699
static int
1700
sframe_xlate_escape_sleb128_to_offsetT (const struct cfi_escape_data *e,
1701
          offsetT *offset)
1702
0
{
1703
0
  gas_assert (e->type == CFI_ESC_byte || e->type == CFI_ESC_sleb128);
1704
  /* Read the offset.  */
1705
0
  if (e->type == CFI_ESC_byte)
1706
0
    {
1707
      /* The user/compiler may provide an sleb128 encoded data of a single byte
1708
   length (DWARF offset of DW_OP_bregN is sleb128).  On a big-endian
1709
   host, the endianness of data itself needs to be accommodated then.  To
1710
   keep it simple, gather the LSB, and translate it to int64.  */
1711
0
      unsigned char sleb_data = e->exp.X_add_number & 0xff;
1712
0
      const unsigned char *buf_start = (const unsigned char *)&sleb_data;
1713
0
      const unsigned char *buf_end = buf_start + 1;
1714
0
      int64_t value = 0;
1715
0
      size_t read = read_sleb128_to_int64 (buf_start, buf_end, &value);
1716
      /* In case of bogus input (highest bit erroneously set, e.g., 0x80),
1717
   gracefully exit.  */
1718
0
      if (!read)
1719
0
  return SFRAME_XLATE_ERR_INVAL;
1720
0
      *offset = (offsetT) value;
1721
0
    }
1722
0
  else
1723
    /* offset must be CFI_ESC_sleb128.  */
1724
0
    *offset = e->exp.X_add_number;
1725
1726
0
  return SFRAME_XLATE_OK;
1727
0
}
1728
1729
/* Handle DW_CFA_def_cfa_expression in .cfi_escape.
1730
1731
   As with sframe_xlate_do_cfi_escape, the intent of this function is to detect
1732
   only the simple-to-process but common cases.  All other CFA escape
1733
   expressions continue to be inadmissible (no SFrame FDE emitted).
1734
1735
   Sets CALLER_WARN_P for skipped cases (and returns SFRAME_XLATE_OK) where the
1736
   caller must warn.  The caller then must also set
1737
   SFRAME_XLATE_ERR_NOTREPRESENTED for their callers.  */
1738
1739
static int
1740
sframe_xlate_do_escape_cfa_expr (struct sframe_xlate_ctx *xlate_ctx,
1741
         const struct cfi_insn_data *cfi_insn,
1742
         bool *caller_warn_p)
1743
0
{
1744
0
  const struct cfi_escape_data *e = cfi_insn->u.esc;
1745
0
  const struct cfi_escape_data *e_offset = NULL;
1746
0
  int err = SFRAME_XLATE_OK;
1747
0
  unsigned int opcode1, opcode2;
1748
0
  offsetT offset = 0;
1749
0
  unsigned int reg = SFRAME_FRE_REG_INVALID;
1750
0
  unsigned int i = 0;
1751
0
  bool x86_cfa_deref_p = false;
1752
1753
  /* Check roughly for an expression like so:
1754
     DW_CFA_def_cfa_expression (DW_OP_breg6 (rbp): -8; DW_OP_deref).  */
1755
0
#define CFI_ESC_NUM_EXP 4
1756
0
  offsetT items[CFI_ESC_NUM_EXP] = {0};
1757
0
  while (e->next)
1758
0
    {
1759
0
      e = e->next;
1760
      /* Bounds check, must be constant, no relocs.  */
1761
0
      if (i >= CFI_ESC_NUM_EXP
1762
0
    || e->exp.X_op != O_constant
1763
0
    || e->reloc != TC_PARSE_CONS_RETURN_NONE)
1764
0
  goto warn_and_exit;
1765
      /* Other checks based on index i.
1766
     - For item[2], allow byte OR sleb128.
1767
     - items at index 0, 1, and 3: Must be byte.  */
1768
0
      if (i == 2 && (e->type != CFI_ESC_byte && e->type != CFI_ESC_sleb128))
1769
0
  goto warn_and_exit;
1770
0
      else if (i != 2 && e->type != CFI_ESC_byte)
1771
0
  goto warn_and_exit;
1772
      /* Block length (items[0]) of 3 in DWARF expr.  */
1773
0
      if (i == 1 && items[0] != 3)
1774
0
  goto warn_and_exit;
1775
1776
0
      if (i == 2)
1777
0
  e_offset = e;
1778
1779
0
      items[i] = e->exp.X_add_number;
1780
0
      i++;
1781
0
    }
1782
1783
0
  if (i != CFI_ESC_NUM_EXP)
1784
0
    goto warn_and_exit;
1785
0
#undef CFI_ESC_NUM_EXP
1786
1787
0
  err = sframe_xlate_escape_sleb128_to_offsetT (e_offset, &offset);
1788
0
  if (err == SFRAME_XLATE_ERR_INVAL)
1789
0
    goto warn_and_exit;
1790
1791
0
  opcode1 = items[1];
1792
0
  opcode2 = items[3];
1793
  /* DW_OP_breg6 is rbp.  FIXME - this stub can be enhanced to handle more
1794
     regs.  */
1795
0
  if (sframe_get_abi_arch () == SFRAME_ABI_AMD64_ENDIAN_LITTLE
1796
0
      && sframe_support_flex_fde_p ()
1797
0
      && opcode1 == DW_OP_breg6 && opcode2 == DW_OP_deref)
1798
0
    {
1799
0
      x86_cfa_deref_p = true;
1800
0
      reg = SFRAME_CFA_FP_REG;
1801
0
    }
1802
1803
0
  struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
1804
0
  gas_assert (cur_fre);
1805
1806
  /* Handle the specific CFA expression mentioned above.  */
1807
0
  if (x86_cfa_deref_p
1808
0
      && sframe_fre_stack_offset_bound_p (offset, false)
1809
0
      && reg != SFRAME_FRE_REG_INVALID)
1810
0
    {
1811
0
      xlate_ctx->flex_p = true;
1812
0
      sframe_fre_set_cfa_base_reg (cur_fre, reg);
1813
0
      sframe_fre_set_cfa_offset (cur_fre, offset);
1814
0
      cur_fre->cfa_deref_p = true;
1815
0
      cur_fre->merge_candidate = false;
1816
      /* Done handling here.  */
1817
0
      caller_warn_p = false;
1818
1819
0
      return err;
1820
0
    }
1821
  /* Any other CFA expression may not be safe to skip.  Fall through to
1822
     warn_and_exit.  */
1823
1824
0
warn_and_exit:
1825
0
  *caller_warn_p = true;
1826
0
  return err;
1827
0
}
1828
1829
/* Handle DW_CFA_expression in .cfi_escape.
1830
1831
   As with sframe_xlate_do_cfi_escape, the intent of this function is to detect
1832
   only the simple-to-process but common cases, where skipping over the escape
1833
   expr data does not affect correctness of the SFrame stack trace data.
1834
1835
   Sets CALLER_WARN_P for skipped cases (and returns SFRAME_XLATE_OK) where the
1836
   caller must warn.  The caller then must also set
1837
   SFRAME_XLATE_ERR_NOTREPRESENTED for their callers.  */
1838
1839
static int
1840
sframe_xlate_do_escape_expr (struct sframe_xlate_ctx *xlate_ctx,
1841
           const struct cfi_insn_data *cfi_insn,
1842
           bool *caller_warn_p)
1843
0
{
1844
0
  const struct cfi_escape_data *e = cfi_insn->u.esc;
1845
0
  const struct cfi_escape_data *e_offset = NULL;
1846
0
  int err = SFRAME_XLATE_OK;
1847
0
  offsetT offset = 0;
1848
0
  unsigned int i = 0;
1849
1850
  /* Check roughly for an expression
1851
     DW_CFA_expression: r1 (rdx) (DW_OP_bregN (reg): OFFSET).  */
1852
0
#define CFI_ESC_NUM_EXP 4
1853
0
  offsetT items[CFI_ESC_NUM_EXP] = {0};
1854
0
  while (e->next)
1855
0
    {
1856
0
      e = e->next;
1857
      /* Bounds check, must be constant, no relocs.  */
1858
0
      if (i >= CFI_ESC_NUM_EXP
1859
0
    || e->exp.X_op != O_constant
1860
0
    || e->reloc != TC_PARSE_CONS_RETURN_NONE)
1861
0
  goto warn_and_exit;
1862
      /* Other checks based on index i.
1863
     - For item[3], allow byte OR sleb128.
1864
     - items at index 0, 1, and 2: Must be byte.  */
1865
0
      if (i == 3 && (e->type != CFI_ESC_byte && e->type != CFI_ESC_sleb128))
1866
0
  goto warn_and_exit;
1867
0
      else if (i != 3 && e->type != CFI_ESC_byte)
1868
0
  goto warn_and_exit;
1869
      /* Block length (items[1]) of 2 in DWARF expr.  */
1870
0
      if (i == 2 && items[1] != 2)
1871
0
  goto warn_and_exit;
1872
1873
0
      if (i == 3)
1874
0
  e_offset = e;
1875
1876
0
      items[i] = e->exp.X_add_number;
1877
0
      i++;
1878
0
    }
1879
1880
0
  if (i <= CFI_ESC_NUM_EXP - 1)
1881
0
    goto warn_and_exit;
1882
0
#undef CFI_ESC_NUM_EXP
1883
1884
0
  err = sframe_xlate_escape_sleb128_to_offsetT (e_offset, &offset);
1885
0
  if (err == SFRAME_XLATE_ERR_INVAL)
1886
0
    goto warn_and_exit;
1887
1888
  /* reg operand to DW_CFA_expression is ULEB128.  For the purpose at hand,
1889
     however, the register value will be less than 128 (CFI_ESC_NUM_EXP set
1890
     to 4).  See an extended comment in sframe_xlate_do_escape_expr for why
1891
     reading ULEB is okay to skip without sacrificing correctness.  */
1892
0
  unsigned int reg = items[0];
1893
1894
0
  unsigned opcode = items[2];
1895
0
  unsigned int fp_base_reg = SFRAME_FRE_REG_INVALID;
1896
0
  bool x86_fp_deref_p = true;
1897
1898
0
  if (sframe_get_abi_arch () == SFRAME_ABI_AMD64_ENDIAN_LITTLE
1899
0
      && sframe_support_flex_fde_p ()
1900
0
      && opcode == DW_OP_breg6)
1901
0
    {
1902
0
      x86_fp_deref_p = true;
1903
0
      fp_base_reg = SFRAME_CFA_FP_REG;
1904
0
    }
1905
1906
0
  struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
1907
0
  gas_assert (cur_fre);
1908
1909
0
  if (x86_fp_deref_p
1910
0
      && reg == SFRAME_CFA_FP_REG
1911
0
      && sframe_fre_stack_offset_bound_p (offset, false))
1912
0
    {
1913
0
      xlate_ctx->flex_p = true;
1914
0
      sframe_fre_set_fp_track (cur_fre, offset);
1915
0
      cur_fre->fp_loc = SFRAME_FRE_ELEM_LOC_REG;
1916
0
      cur_fre->fp_reg = fp_base_reg;
1917
0
      cur_fre->fp_deref_p = true;
1918
0
      cur_fre->merge_candidate = false;
1919
0
    }
1920
0
  else if (reg == SFRAME_CFA_SP_REG || reg == SFRAME_CFA_FP_REG
1921
0
     || (sframe_ra_tracking_p () && reg == SFRAME_CFA_RA_REG)
1922
0
     || reg == sframe_xlate_ctx_get_cur_cfa_reg (xlate_ctx))
1923
0
    {
1924
0
      as_warn (_("no SFrame FDE emitted; "
1925
0
     ".cfi_escape DW_CFA_expression with %s reg %u"),
1926
0
         sframe_register_name (reg), reg);
1927
0
      err = SFRAME_XLATE_ERR_NOTREPRESENTED;
1928
0
    }
1929
  /* else safe to skip, so continue to return SFRAME_XLATE_OK.  */
1930
1931
0
  return err;
1932
1933
0
warn_and_exit:
1934
0
  *caller_warn_p = true;
1935
0
  return err;
1936
0
}
1937
1938
/* Handle DW_CFA_val_offset in .cfi_escape.
1939
1940
   As with sframe_xlate_do_cfi_escape, the intent of this function is to detect
1941
   only the simple-to-process but common cases, where skipping over the escape
1942
   expr data does not affect correctness of the SFrame stack trace data.
1943
1944
   Sets CALLER_WARN_P for skipped cases (and returns SFRAME_XLATE_OK) where the
1945
   caller must warn.  The caller then must also set
1946
   SFRAME_XLATE_ERR_NOTREPRESENTED for their callers.  */
1947
1948
static int
1949
sframe_xlate_do_escape_val_offset (const struct sframe_xlate_ctx *xlate_ctx,
1950
           const struct cfi_insn_data *cfi_insn,
1951
           bool *caller_warn_p)
1952
0
{
1953
0
  const struct cfi_escape_data *e = cfi_insn->u.esc;
1954
0
  int err = SFRAME_XLATE_OK;
1955
0
  unsigned int i = 0;
1956
0
  unsigned int reg;
1957
0
  offsetT offset;
1958
1959
  /* Check for (DW_CFA_val_offset reg scaled_offset) sequence.  */
1960
0
#define CFI_ESC_NUM_EXP 2
1961
0
  offsetT items[CFI_ESC_NUM_EXP] = {0};
1962
0
  while (e->next)
1963
0
    {
1964
0
      e = e->next;
1965
0
      if (i >= CFI_ESC_NUM_EXP || e->exp.X_op != O_constant
1966
0
    || e->type != CFI_ESC_byte
1967
0
    || e->reloc != TC_PARSE_CONS_RETURN_NONE)
1968
0
  goto warn_and_exit;
1969
0
      items[i] = e->exp.X_add_number;
1970
0
      i++;
1971
0
    }
1972
0
  if (i <= CFI_ESC_NUM_EXP - 1)
1973
0
    goto warn_and_exit;
1974
1975
  /* Both arguments to DW_CFA_val_offset are ULEB128.  Especially with APX (on
1976
     x86) we're going to see DWARF register numbers above 127, for the extended
1977
     GPRs.  And large enough stack frames would also require multi-byte offset
1978
     representation.  However, since we limit our focus on cases when
1979
     CFI_ESC_NUM_EXP is 2, reading ULEB can be skipped.  IOW, although not
1980
     ideal, SFrame FDE generation in case of an APX register in
1981
     DW_CFA_val_offset is being skipped (PS: this does _not_ mean incorrect
1982
     SFrame stack trace data).
1983
1984
     Recall that the intent here is to check for simple and prevalent cases,
1985
     when feasible.  */
1986
1987
0
  reg = items[0];
1988
0
  offset = items[1];
1989
0
#undef CFI_ESC_NUM_EXP
1990
1991
  /* Invoke sframe_xlate_do_val_offset itself for checking.  */
1992
0
  struct cfi_insn_data temp = {
1993
0
    .insn = DW_CFA_val_offset,
1994
0
    .u = {
1995
0
      .ri = {
1996
0
  .reg = reg,
1997
0
  .offset = offset * DWARF2_CIE_DATA_ALIGNMENT
1998
0
      }
1999
0
    }
2000
0
  };
2001
0
  err = sframe_xlate_do_val_offset (xlate_ctx, &temp, true);
2002
0
  return err;
2003
2004
0
warn_and_exit:
2005
0
  *caller_warn_p = true;
2006
0
  return err;
2007
0
}
2008
2009
/* Handle DW_CFA_GNU_args_size in .cfi_escape.
2010
2011
   The purpose of DW_CFA_GNU_args_size is to adjust SP when performing stack
2012
   unwinding for exception handling.  For stack tracing needs,
2013
   DW_CFA_GNU_args_size can be ignored, when CFA is FP-based.  This is because
2014
   if the topmost frame is that of the catch block, the SP has been restored to
2015
   correct value by exception handling logic.  From this point of interest in
2016
   the catch block now, stack tracing intends to go backwards to the caller
2017
   frame.  If CFA restoration does not need SP, DW_CFA_GNU_args_size can be
2018
   ignored for stack tracing.
2019
2020
   Continue to warn and not emit SFrame FDE if CFA is SP based.  The pattern
2021
   where the CFA is SP based and there is a DW_CFA_GNU_args_size for
2022
   SP-adjustment is not entirely clear.
2023
2024
   Sets CALLER_WARN_P for skipped cases (and returns SFRAME_XLATE_OK) where the
2025
   caller must warn.  The caller then must also set
2026
   SFRAME_XLATE_ERR_NOTREPRESENTED for their callers.  */
2027
2028
static int
2029
sframe_xlate_do_escape_gnu_args_size (const struct sframe_xlate_ctx *xlate_ctx,
2030
              const struct cfi_insn_data *cfi_insn,
2031
              bool *caller_warn_p)
2032
0
{
2033
0
  const struct cfi_escape_data *e = cfi_insn->u.esc;
2034
0
  unsigned int i = 0;
2035
2036
  /* Check for (DW_CFA_GNU_args_size offset) sequence.  */
2037
0
#define CFI_ESC_NUM_EXP 1
2038
0
  offsetT items[CFI_ESC_NUM_EXP] = {0};
2039
0
  while (e->next)
2040
0
    {
2041
0
      e = e->next;
2042
0
      if (i >= CFI_ESC_NUM_EXP || e->exp.X_op != O_constant
2043
0
    || e->type != CFI_ESC_byte
2044
0
    || e->reloc != TC_PARSE_CONS_RETURN_NONE)
2045
0
  goto warn_and_exit;
2046
0
      items[i] = e->exp.X_add_number;
2047
0
      i++;
2048
0
    }
2049
0
  if (i == 0)
2050
0
    goto warn_and_exit;
2051
2052
0
#undef CFI_ESC_NUM_EXP
2053
2054
0
  offsetT offset = items[0];
2055
2056
0
  struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
2057
0
  gas_assert (cur_fre);
2058
 /* If CFA is FP based, safe to skip.  */
2059
0
  if (offset == 0
2060
0
      || sframe_xlate_ctx_get_cur_cfa_reg (xlate_ctx) == SFRAME_CFA_FP_REG)
2061
0
    return SFRAME_XLATE_OK;
2062
2063
0
warn_and_exit:
2064
0
  *caller_warn_p = true;
2065
0
  return SFRAME_XLATE_OK;
2066
0
}
2067
2068
/* Handle CFI_escape in SFrame context.
2069
2070
   .cfi_escape CFI directive allows the user to add arbitrary data to the
2071
   unwind info.  DWARF expressions commonly follow after CFI_escape (fake CFI)
2072
   DWARF opcode.  One might also use CFI_escape to add OS-specific CFI opcodes
2073
   even.
2074
2075
   Complex unwind info added using .cfi_escape directive _may_ be of no
2076
   consequence for SFrame when the affected registers are not SP, FP, RA or
2077
   CFA.  The challenge in confirming the afore-mentioned is that it needs full
2078
   parsing (and validation) of the data presented after .cfi_escape.  Here we
2079
   take a case-by-case approach towards skipping _some_ instances of
2080
   .cfi_escape: skip those that can be *easily* determined to be harmless in
2081
   the context of SFrame stack trace information.
2082
2083
   This function partially processes data following .cfi_escape and returns
2084
   SFRAME_XLATE_OK if OK to skip.  */
2085
2086
static int
2087
sframe_xlate_do_cfi_escape (struct sframe_xlate_ctx *xlate_ctx,
2088
          const struct cfi_insn_data *cfi_insn)
2089
14
{
2090
14
  const struct cfi_escape_data *e;
2091
14
  bool warn_p = false;
2092
14
  int err = SFRAME_XLATE_OK;
2093
14
  offsetT firstop;
2094
2095
14
  e = cfi_insn->u.esc;
2096
2097
14
  if (!e)
2098
0
    return SFRAME_XLATE_ERR_INVAL;
2099
2100
14
  if (e->exp.X_op != O_constant
2101
9
      || e->type != CFI_ESC_byte
2102
9
      || e->reloc != TC_PARSE_CONS_RETURN_NONE)
2103
5
    return SFRAME_XLATE_ERR_NOTREPRESENTED;
2104
2105
9
  firstop = e->exp.X_add_number;
2106
9
  switch (firstop)
2107
9
    {
2108
9
    case DW_CFA_nop:
2109
      /* One or more nops together are harmless for SFrame.  */
2110
13
      while (e->next)
2111
4
  {
2112
4
    e = e->next;
2113
4
    if (e->exp.X_op != O_constant || e->exp.X_add_number != DW_CFA_nop
2114
4
        || e->type != CFI_ESC_byte
2115
4
        || e->reloc != TC_PARSE_CONS_RETURN_NONE)
2116
0
      {
2117
0
        warn_p = true;
2118
0
        break;
2119
0
      }
2120
4
  }
2121
9
      break;
2122
2123
0
    case DW_CFA_def_cfa_expression:
2124
0
      err = sframe_xlate_do_escape_cfa_expr (xlate_ctx, cfi_insn, &warn_p);
2125
0
      break;
2126
2127
0
    case DW_CFA_expression:
2128
0
      err = sframe_xlate_do_escape_expr (xlate_ctx, cfi_insn, &warn_p);
2129
0
      break;
2130
2131
0
    case DW_CFA_val_offset:
2132
0
      err = sframe_xlate_do_escape_val_offset (xlate_ctx, cfi_insn, &warn_p);
2133
0
      break;
2134
2135
0
    case DW_CFA_GNU_args_size:
2136
0
      err = sframe_xlate_do_escape_gnu_args_size (xlate_ctx, cfi_insn, &warn_p);
2137
0
      break;
2138
2139
0
    default:
2140
0
      warn_p = true;
2141
0
      break;
2142
9
    }
2143
2144
9
  if (warn_p)
2145
0
    {
2146
      /* In all other cases (e.g., DW_CFA_def_cfa_expression or other
2147
   OS-specific CFI opcodes), skip inspecting the DWARF expression.
2148
   This may impact the asynchronicity due to loss of coverage.
2149
   Continue to warn the user and bail out.  */
2150
0
      as_warn (_("no SFrame FDE emitted; .cfi_escape with op (%#lx)"),
2151
0
         (unsigned long)firstop);
2152
0
      err = SFRAME_XLATE_ERR_NOTREPRESENTED;
2153
0
    }
2154
2155
9
  return err;
2156
9
}
2157
2158
/* Translate DW_CFA_undefined into SFrame context.
2159
2160
   DW_CFA_undefined op indicates that from now on, the previous value of
2161
   register can’t be restored anymore.  In DWARF, for the return address (RA)
2162
   register, this indicates to an unwinder that there is no return address
2163
   and the unwind is complete.
2164
2165
   In SFrame, represent the use of the RA register with DW_CFA_undefined as
2166
   SFrame FRE without any trailing FRE data words.  Stack tracers can use this
2167
   as indication that an outermost frame has been reached and the stack trace
2168
   is complete.  The use of other registers of interest with  DW_CFA_undefined
2169
   cannot be represented in SFrame.  Therefore skip generating an SFrame FDE.
2170
2171
   Return SFRAME_XLATE_OK if success.  */
2172
2173
static int
2174
sframe_xlate_do_cfi_undefined (const struct sframe_xlate_ctx *xlate_ctx ATTRIBUTE_UNUSED,
2175
             const struct cfi_insn_data *cfi_insn)
2176
36
{
2177
36
  if (cfi_insn->u.r == SFRAME_CFA_FP_REG
2178
36
      || cfi_insn->u.r == SFRAME_CFA_SP_REG)
2179
0
    {
2180
0
      as_warn (_("no SFrame FDE emitted; %s reg %u in .cfi_undefined"),
2181
0
         sframe_register_name (cfi_insn->u.r), cfi_insn->u.r);
2182
0
      return SFRAME_XLATE_ERR_NOTREPRESENTED; /* Not represented.  */
2183
0
    }
2184
36
  else if (cfi_insn->u.r == SFRAME_CFA_RA_REG)
2185
0
    {
2186
      /* Represent RA undefined (i.e. outermost frame) as FRE without any
2187
   data words.  */
2188
0
      struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
2189
2190
0
      gas_assert (cur_fre);
2191
      /* Set RA undefined status bit.  */
2192
0
      cur_fre->ra_undefined_p = true;
2193
0
      cur_fre->merge_candidate = false;
2194
0
    }
2195
2196
36
  return SFRAME_XLATE_OK;
2197
36
}
2198
2199
/* Translate DW_CFA_same_value into SFrame context.
2200
2201
   DW_CFA_same_value op indicates that current value of register is the same as
2202
   in the previous frame, i.e. no restoration needed.  In SFrame stack trace
2203
   format, the handling is done similar to DW_CFA_restore.
2204
2205
   For SFRAME_CFA_RA_REG, if RA-tracking is enabled, reset the SFrame FRE state
2206
   for REG_RA to indicate that register does not need restoration.  P.S.: Even
2207
   though resetting just REG_RA may be contradicting the AArch64 ABI (as Frame
2208
   Record contains for FP and LR), sframe_xlate_do_same_value () does not
2209
   detect the case and assumes the users' DW_CFA_same_value SFRAME_CFA_RA_REG
2210
   has a sound reason.  For ABIs, where RA-tracking is disabled, handle it
2211
   similar to DW_CFA_restore: ignore the directive, it is safe to skip.  The
2212
   reasoning is similar to that for DW_CFA_restore: if such a restoration was
2213
   meant to be of any consequence, there must have been the necessary CFI
2214
   directives for updating the CFA rule too such that the recovered RA from
2215
   stack is valid.
2216
2217
   SFrame based stacktracers will implement CFA-based SP recovery for all ABIs:
2218
   SP for previous frame is based on the applicable CFA-rule.  There is no
2219
   representation in SFrame to indicate "no restoration needed" for REG_SP,
2220
   when going to the previous frame.  That said, if DW_CFA_same_value is seen
2221
   for SFRAME_CFA_SP_REG, handle it similar to DW_CFA_restore: ignore the
2222
   directive, it is safe to skip.  The reasoning is similar to that for
2223
   DW_CFA_restore: if such a restoration was meant to be of any consequence,
2224
   there must have been the necessary CFI directives for updating the CFA rule
2225
   too.  The latter will be duly processed by the SFrame generation code, as
2226
   expected.
2227
2228
   For SFRAME_CFA_FP_REG, reset the state of the current FRE to indicate that
2229
   the value is the same as previous frame.
2230
2231
   Return SFRAME_XLATE_OK if success.  */
2232
2233
static int
2234
sframe_xlate_do_same_value (const struct sframe_xlate_ctx *xlate_ctx,
2235
          const struct cfi_insn_data *cfi_insn)
2236
2
{
2237
2
  struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
2238
2239
2
  if (sframe_ra_tracking_p () && cfi_insn->u.r == SFRAME_CFA_RA_REG)
2240
0
    {
2241
0
      cur_fre->ra_loc = SFRAME_FRE_ELEM_LOC_NONE;
2242
0
      cur_fre->ra_offset = 0;
2243
0
      cur_fre->ra_undefined_p = false;
2244
0
      cur_fre->merge_candidate = false;
2245
0
    }
2246
2
  else if (cfi_insn->u.r == SFRAME_CFA_FP_REG)
2247
0
    {
2248
0
      cur_fre->fp_loc = SFRAME_FRE_ELEM_LOC_NONE;
2249
0
      cur_fre->fp_offset = 0;
2250
0
      cur_fre->merge_candidate = false;
2251
0
    }
2252
2253
  /* Safe to skip.  */
2254
2
  return SFRAME_XLATE_OK;
2255
2
}
2256
2257
/* Returns the DWARF call frame instruction name or fake CFI name for the
2258
   specified CFI opcode, or NULL if the value is not recognized.  */
2259
2260
static const char *
2261
sframe_get_cfi_name (int cfi_opc)
2262
1
{
2263
1
  const char *cfi_name;
2264
2265
1
  switch (cfi_opc)
2266
1
    {
2267
      /* Fake CFI type; outside the byte range of any real CFI insn.  */
2268
      /* See gas/dw2gencfi.h.  */
2269
0
      case CFI_adjust_cfa_offset:
2270
0
  cfi_name = "CFI_adjust_cfa_offset";
2271
0
  break;
2272
0
      case CFI_return_column:
2273
0
  cfi_name = "CFI_return_column";
2274
0
  break;
2275
0
      case CFI_rel_offset:
2276
0
  cfi_name = "CFI_rel_offset";
2277
0
  break;
2278
0
      case CFI_escape:
2279
0
  cfi_name = "CFI_escape";
2280
0
  break;
2281
0
      case CFI_signal_frame:
2282
0
  cfi_name = "CFI_signal_frame";
2283
0
  break;
2284
1
      case CFI_val_encoded_addr:
2285
1
  cfi_name = "CFI_val_encoded_addr";
2286
1
  break;
2287
0
      case CFI_label:
2288
0
  cfi_name = "CFI_label";
2289
0
  break;
2290
0
      default:
2291
0
  cfi_name = get_DW_CFA_name (cfi_opc);
2292
1
    }
2293
2294
1
  return cfi_name;
2295
1
}
2296
2297
/* Process CFI_INSN and update the translation context with the FRE
2298
   information.
2299
2300
   Returns an error code (sframe_xlate_err) if CFI_INSN is not successfully
2301
   processed.  */
2302
2303
static int
2304
sframe_do_cfi_insn (struct sframe_xlate_ctx *xlate_ctx,
2305
        const struct cfi_insn_data *cfi_insn)
2306
280
{
2307
280
  int err = 0;
2308
2309
  /* Atleast one cfi_insn per FDE is expected.  */
2310
280
  gas_assert (cfi_insn);
2311
280
  int op = cfi_insn->insn;
2312
2313
280
  switch (op)
2314
280
    {
2315
47
    case DW_CFA_advance_loc:
2316
47
      err = sframe_xlate_do_advance_loc (xlate_ctx, cfi_insn);
2317
47
      break;
2318
55
    case DW_CFA_def_cfa:
2319
55
      err = sframe_xlate_do_def_cfa (xlate_ctx, cfi_insn);
2320
55
      break;
2321
13
    case DW_CFA_def_cfa_register:
2322
13
      err = sframe_xlate_do_def_cfa_register (xlate_ctx, cfi_insn);
2323
13
      break;
2324
10
    case DW_CFA_def_cfa_offset:
2325
10
      err = sframe_xlate_do_def_cfa_offset (xlate_ctx, cfi_insn);
2326
10
      break;
2327
60
    case DW_CFA_offset:
2328
60
      err = sframe_xlate_do_offset (xlate_ctx, cfi_insn);
2329
60
      break;
2330
9
    case DW_CFA_val_offset:
2331
9
      err = sframe_xlate_do_val_offset (xlate_ctx, cfi_insn, false);
2332
9
      break;
2333
0
    case DW_CFA_remember_state:
2334
0
      err = sframe_xlate_do_remember_state (xlate_ctx);
2335
0
      break;
2336
0
    case DW_CFA_restore_state:
2337
0
      err = sframe_xlate_do_restore_state (xlate_ctx);
2338
0
      break;
2339
11
    case DW_CFA_restore:
2340
11
      err = sframe_xlate_do_restore (xlate_ctx, cfi_insn);
2341
11
      break;
2342
    /* DW_CFA_AARCH64_negate_ra_state is multiplexed with
2343
       DW_CFA_GNU_window_save.  */
2344
0
    case DW_CFA_GNU_window_save:
2345
0
      err = sframe_xlate_do_gnu_window_save (xlate_ctx, cfi_insn);
2346
0
      break;
2347
0
    case DW_CFA_AARCH64_negate_ra_state_with_pc:
2348
0
      err = sframe_xlate_do_aarch64_negate_ra_state_with_pc (xlate_ctx, cfi_insn);
2349
0
      break;
2350
22
    case DW_CFA_register:
2351
22
      err = sframe_xlate_do_register (xlate_ctx, cfi_insn);
2352
22
      break;
2353
14
    case CFI_escape:
2354
14
      err = sframe_xlate_do_cfi_escape (xlate_ctx, cfi_insn);
2355
14
      break;
2356
36
    case DW_CFA_undefined:
2357
36
      err = sframe_xlate_do_cfi_undefined (xlate_ctx, cfi_insn);
2358
36
      break;
2359
2
    case DW_CFA_same_value:
2360
2
      err = sframe_xlate_do_same_value (xlate_ctx, cfi_insn);
2361
2
      break;
2362
1
    default:
2363
      /* Other skipped operations may, however, impact the asynchronicity.  */
2364
1
      {
2365
1
  const char *cfi_name = sframe_get_cfi_name (op);
2366
2367
1
  if (!cfi_name)
2368
0
    cfi_name = _("(unknown)");
2369
1
  as_warn (_("no SFrame FDE emitted; CFI insn %s (%#x)"),
2370
1
     cfi_name, op);
2371
1
  err = SFRAME_XLATE_ERR_NOTREPRESENTED;
2372
1
      }
2373
280
    }
2374
2375
  /* Any error will cause no SFrame FDE later.  The user has already been
2376
     warned.  */
2377
280
  return err;
2378
280
}
2379
2380
2381
static int
2382
sframe_do_fde (struct sframe_xlate_ctx *xlate_ctx,
2383
         const struct fde_entry *dw_fde)
2384
37
{
2385
37
  const struct cfi_insn_data *cfi_insn;
2386
37
  int err = SFRAME_XLATE_OK;
2387
2388
37
  xlate_ctx->dw_fde = dw_fde;
2389
2390
  /* SFrame format cannot represent a non-default DWARF return column reg.  */
2391
37
  if (xlate_ctx->dw_fde->return_column != DWARF2_DEFAULT_RETURN_COLUMN)
2392
0
    {
2393
0
      as_warn (_("no SFrame FDE emitted; non-default RA register %u"),
2394
0
         xlate_ctx->dw_fde->return_column);
2395
0
      return SFRAME_XLATE_ERR_NOTREPRESENTED;
2396
0
    }
2397
2398
  /* Iterate over the CFIs and create SFrame FREs.  */
2399
307
  for (cfi_insn = dw_fde->data; cfi_insn; cfi_insn = cfi_insn->next)
2400
280
    {
2401
      /* Translate each CFI, and buffer the state in translation context.  */
2402
280
      err = sframe_do_cfi_insn (xlate_ctx, cfi_insn);
2403
280
      if (err != SFRAME_XLATE_OK)
2404
10
  {
2405
    /* Skip generating SFrame stack trace info for the function if any
2406
       offending CFI is encountered by sframe_do_cfi_insn ().  Warning
2407
       message already printed by sframe_do_cfi_insn ().  */
2408
10
    return err; /* Return the error code.  */
2409
10
  }
2410
280
    }
2411
2412
  /* Link in the scratchpad FRE that the last few CFI insns helped create.  */
2413
27
  if (xlate_ctx->cur_fre)
2414
27
    {
2415
27
      sframe_xlate_ctx_add_fre (xlate_ctx, xlate_ctx->cur_fre);
2416
27
      xlate_ctx->cur_fre = NULL;
2417
27
    }
2418
  /* Designate the end of the last SFrame FRE.  */
2419
27
  if (xlate_ctx->last_fre)
2420
27
    {
2421
27
      xlate_ctx->last_fre->pc_end
2422
27
  = get_dw_fde_end_addrS (xlate_ctx->dw_fde);
2423
27
    }
2424
2425
  /* Number of FREs must fit uint16_t.  Check now, and do not emit the SFrame
2426
     FDE if it doesnt fit (although, it is not expected to happen for
2427
     real-world, useful programs).  The approach of truncating the FDE and
2428
     emitting multiple SFrame FDEs instead, is not a clearly preferable
2429
     handling either.  Its a divergence from the model where an SFrame FDE
2430
     encodes stack trace data between a .cfi_startproc and .cfi_endproc pair.
2431
     Further, some components (linkers, stack tracers) want to associate the
2432
     Start PC of a function to a known symbol in the file?  */
2433
27
  if (xlate_ctx->num_xlate_fres > UINT16_MAX)
2434
0
    {
2435
0
      as_warn (_("no SFrame FDE emitted; Number of FREs exceeds UINT16_MAX"));
2436
0
      return SFRAME_XLATE_ERR_NOTREPRESENTED;
2437
0
    }
2438
2439
  /* ABI/arch except s390x cannot represent FP without RA saved.  */
2440
27
  if (sframe_ra_tracking_p ()
2441
0
      && sframe_get_abi_arch () != SFRAME_ABI_S390X_ENDIAN_BIG)
2442
0
    {
2443
0
      struct sframe_row_entry *fre;
2444
2445
      /* Iterate over the scratchpad FREs and validate them.  */
2446
0
      for (fre = xlate_ctx->first_fre; fre; fre = fre->next)
2447
0
  {
2448
    /* SFrame format cannot represent FP on stack without RA on stack.  */
2449
0
    if (fre->ra_loc != SFRAME_FRE_ELEM_LOC_STACK
2450
0
        && fre->fp_loc == SFRAME_FRE_ELEM_LOC_STACK)
2451
0
      {
2452
0
        as_warn (_("no SFrame FDE emitted; FP without RA on stack"));
2453
0
        return SFRAME_XLATE_ERR_NOTREPRESENTED;
2454
0
      }
2455
0
  }
2456
0
    }
2457
2458
27
  return SFRAME_XLATE_OK;
2459
27
}
2460
2461
/* Create SFrame stack trace info for all functions.
2462
2463
   This function consumes the already generated DWARF FDEs (by dw2gencfi) and
2464
   generates data which is later emitted as stack trace information encoded in
2465
   the SFrame format.  */
2466
2467
static void
2468
create_sframe_all (void)
2469
35
{
2470
35
  struct fde_entry *dw_fde = NULL;
2471
35
  struct sframe_func_entry *sframe_fde = NULL;
2472
2473
35
  struct sframe_xlate_ctx *xlate_ctx = sframe_xlate_ctx_alloc ();
2474
2475
72
  for (dw_fde = all_fde_data; dw_fde ; dw_fde = dw_fde->next)
2476
37
    {
2477
37
      sframe_fde = sframe_fde_alloc ();
2478
      /* Initialize the translation context with information anew.  */
2479
37
      sframe_xlate_ctx_init (xlate_ctx);
2480
2481
      /* Report and fix open CFI.  */
2482
37
      if (dw_fde->end_address == NULL)
2483
33
  {
2484
33
    as_bad (_("open CFI at the end of file; "
2485
33
        "missing .cfi_endproc directive"));
2486
33
    dw_fde->end_address = dw_fde->start_address;
2487
33
  }
2488
2489
      /* Process and link SFrame FDEs if no error.  */
2490
37
      int err = sframe_do_fde (xlate_ctx, dw_fde);
2491
37
      if (err && get_dw_fde_signal_p (dw_fde))
2492
0
  {
2493
0
    sframe_xlate_ctx_cleanup (xlate_ctx);
2494
0
    xlate_ctx->flex_p = false;
2495
0
    err = SFRAME_XLATE_OK;
2496
0
  }
2497
2498
37
      if (err)
2499
10
  {
2500
10
    sframe_xlate_ctx_cleanup (xlate_ctx);
2501
10
    sframe_fde_free (sframe_fde);
2502
10
  }
2503
27
      else
2504
27
  {
2505
    /* All done.  Transfer the state from the SFrame translation
2506
       context to the SFrame FDE.  */
2507
27
    sframe_xlate_ctx_finalize (xlate_ctx, sframe_fde);
2508
27
    *last_sframe_fde = sframe_fde;
2509
27
    last_sframe_fde = &sframe_fde->next;
2510
27
  }
2511
37
    }
2512
2513
35
  XDELETE (xlate_ctx);
2514
35
}
2515
2516
void
2517
output_sframe (segT sframe_seg)
2518
35
{
2519
35
  (void) sframe_seg;
2520
2521
  /* Currently only SFRAME_VERSION_3 can be emitted.  */
2522
35
  gas_assert (flag_gen_sframe_version == GEN_SFRAME_VERSION_3);
2523
  /* Setup the version specific access functions.  */
2524
35
  sframe_set_version (flag_gen_sframe_version);
2525
2526
  /* Process all fdes and create SFrame stack trace information.  */
2527
35
  create_sframe_all ();
2528
2529
35
  output_sframe_internal ();
2530
35
}
2531
2532
#else  /*  support_sframe_p  */
2533
2534
void
2535
output_sframe (segT sframe_seg ATTRIBUTE_UNUSED)
2536
{
2537
}
2538
2539
#endif /*  support_sframe_p  */