Coverage Report

Created: 2026-03-10 08:46

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
18
# 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
8
# 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
36
{
74
36
  FRAG_APPEND_1_CHAR (byte);
75
36
}
76
77
/* Emit a two-byte word into the current segment.  */
78
79
static inline void
80
out_two (int data)
81
6
{
82
6
  md_number_to_chars (frag_more (2), data, 2);
83
6
}
84
85
/* Emit a four byte word into the current segment.  */
86
87
static inline void
88
out_four (int data)
89
6
{
90
6
  md_number_to_chars (frag_more (4), data, 4);
91
6
}
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
14
{
98
14
  return dw_fde->start_address;
99
14
}
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
14
{
106
14
  return dw_fde->end_address;
107
14
}
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
3
{
113
#ifdef tc_fde_entry_extras
114
  return (dw_fde->pauth_key == AARCH64_PAUTH_KEY_B);
115
#else
116
3
  return false;
117
3
#endif
118
3
}
119
120
/* Get whether signal frame.  */
121
static bool
122
get_dw_fde_signal_p (const struct fde_entry *dw_fde)
123
3
{
124
3
  return (dw_fde->signal_frame == 1);
125
3
}
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
7
{
132
7
  fre->pc_begin = beginS;
133
7
}
134
135
static void
136
sframe_fre_set_end_addr (struct sframe_row_entry *fre, symbolS *endS)
137
4
{
138
4
  fre->pc_end = endS;
139
4
}
140
141
static void
142
sframe_fre_set_cfa_base_reg (struct sframe_row_entry *fre,
143
           unsigned int cfa_base_reg)
144
4
{
145
4
  fre->cfa_base_reg = cfa_base_reg;
146
4
  fre->merge_candidate = false;
147
4
}
148
149
static offsetT
150
sframe_fre_get_cfa_offset (const struct sframe_row_entry * fre)
151
0
{
152
0
  offsetT offset = fre->cfa_offset;
153
154
  /* For s390x undo adjustment of CFA offset (to enable 8-bit offsets).  */
155
0
  if (sframe_get_abi_arch () == SFRAME_ABI_S390X_ENDIAN_BIG)
156
0
    offset = SFRAME_V2_S390X_CFA_OFFSET_DECODE (offset);
157
158
0
  return offset;
159
0
}
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
4
{
172
  /* For s390x, CFA offset is adjusted to enable 8-bit offsets.  */
173
4
  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
4
  return (offset >= INT32_MIN && offset <= INT32_MAX);
177
4
}
178
179
static void
180
sframe_fre_set_cfa_offset (struct sframe_row_entry *fre,
181
         offsetT cfa_offset)
182
4
{
183
  /* For s390x adjust CFA offset to enable 8-bit offsets.  */
184
4
  if (sframe_get_abi_arch () == SFRAME_ABI_S390X_ENDIAN_BIG)
185
0
    cfa_offset = SFRAME_V2_S390X_CFA_OFFSET_ENCODE (cfa_offset);
186
187
4
  fre->cfa_offset = cfa_offset;
188
4
  fre->merge_candidate = false;
189
4
}
190
191
static void
192
sframe_fre_set_ra_track (struct sframe_row_entry *fre, offsetT ra_offset)
193
0
{
194
0
  fre->ra_loc = SFRAME_FRE_ELEM_LOC_STACK;
195
0
  fre->ra_offset = ra_offset;
196
0
  fre->ra_undefined_p = false;
197
0
  fre->merge_candidate = false;
198
0
}
199
200
static void
201
sframe_fre_set_fp_track (struct sframe_row_entry *fre, offsetT fp_offset)
202
0
{
203
0
  fre->fp_loc = SFRAME_FRE_ELEM_LOC_STACK;
204
0
  fre->fp_offset = fp_offset;
205
0
  fre->merge_candidate = false;
206
0
}
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
5
{
213
5
  unsigned int size = 0;
214
215
5
  if (value == (int8_t)value)
216
5
    size = 1;
217
0
  else if (value == (int16_t)value)
218
0
    size = 2;
219
0
  else if (value == (int32_t)value)
220
0
    size = 4;
221
0
  else
222
0
    return 8;
223
224
5
  return size;
225
5
}
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
2
{
232
2
  unsigned int size = 0;
233
234
2
  if (value <= UINT8_MAX)
235
2
    size = 1;
236
0
  else if (value <= UINT16_MAX)
237
0
    size = 2;
238
0
  else
239
0
    size = 4;
240
241
2
  return size;
242
2
}
243
5
#define SFRAME_FRE_DATAWORD_FUNC_MAP_INDEX_1B  0 /* SFRAME_FRE_DATAWORD_1B.  */
244
0
#define SFRAME_FRE_DATAWORD_FUNC_MAP_INDEX_2B  1 /* SFRAME_FRE_DATAWORD_2B.  */
245
0
#define SFRAME_FRE_DATAWORD_FUNC_MAP_INDEX_4B  2 /* SFRAME_FRE_DATAWORD_4B.  */
246
5
#define SFRAME_FRE_DATAWORD_FUNC_MAP_INDEX_8B  3 /* Not supported in SFrame.  */
247
#define SFRAME_FRE_DATAWORD_FUNC_MAP_INDEX_MAX \
248
5
  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
5
{
263
5
  unsigned int idx = SFRAME_FRE_DATAWORD_FUNC_MAP_INDEX_MAX;
264
265
5
  switch (dataword_size)
266
5
    {
267
5
      case SFRAME_FRE_DATAWORD_1B:
268
5
  idx = SFRAME_FRE_DATAWORD_FUNC_MAP_INDEX_1B;
269
5
  break;
270
0
      case SFRAME_FRE_DATAWORD_2B:
271
0
  idx = SFRAME_FRE_DATAWORD_FUNC_MAP_INDEX_2B;
272
0
  break;
273
0
      case SFRAME_FRE_DATAWORD_4B:
274
0
  idx = SFRAME_FRE_DATAWORD_FUNC_MAP_INDEX_4B;
275
0
  break;
276
0
      default:
277
  /* Not supported in SFrame.  */
278
0
  break;
279
5
    }
280
281
5
  return idx;
282
5
}
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
5
{
306
5
  unsigned char fre_info;
307
5
  fre_info = SFRAME_V1_FRE_INFO (cfa_base_reg, dataword_count, dataword_size);
308
5
  fre_info = SFRAME_V1_FRE_INFO_UPDATE_MANGLED_RA_P (mangled_ra_p, fre_info);
309
5
  return fre_info;
310
5
}
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
3
{
318
3
  unsigned char func_info;
319
3
  func_info = SFRAME_V3_FDE_FUNC_INFO (fde_pc_type, fre_type);
320
3
  func_info = SFRAME_V3_FDE_UPDATE_PAUTH_KEY (pauth_key, func_info);
321
3
  func_info = SFRAME_V3_FDE_UPDATE_SIGNAL_P (signal_p, func_info);
322
3
  return func_info;
323
3
}
324
325
/* SFrame version specific operations setup.  */
326
327
static void
328
sframe_set_version (enum gen_sframe_version flag_ver)
329
3
{
330
3
  if (flag_ver == GEN_SFRAME_VERSION_3)
331
3
    {
332
3
      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
3
      sframe_ver_ops.set_fre_info = sframe_v1_set_fre_info;
337
3
      sframe_ver_ops.set_func_info = sframe_v3_set_func_info;
338
3
    }
339
3
}
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
5
{
347
5
  return sframe_ver_ops.set_fre_info (cfa_base_reg, dataword_count,
348
5
              dataword_size, mangled_ra_p);
349
5
}
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
3
{
357
3
  return sframe_ver_ops.set_func_info (fde_type, fre_type, pauth_key,
358
3
               signal_p);
359
3
}
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
5
{
376
5
  unsigned int cfi_insn_cfa_base_reg = sframe_fre->cfa_base_reg;
377
5
  unsigned fre_base_reg = SFRAME_BASE_REG_SP;
378
379
5
  if (cfi_insn_cfa_base_reg == SFRAME_CFA_FP_REG)
380
0
    fre_base_reg = SFRAME_BASE_REG_FP;
381
382
  /* Only one bit is reserved in SFRAME_VERSION_1.  */
383
5
  gas_assert (fre_base_reg == SFRAME_BASE_REG_SP
384
5
        || fre_base_reg == SFRAME_BASE_REG_FP);
385
386
5
  return fre_base_reg;
387
5
}
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
5
{
394
  /* For SFRAME_FDE_TYPE_FLEX FDE type, each entity (CFA, FP, RA) may carry up
395
     to two data words.  */
396
5
  unsigned int count = flex_p ? 2 : 1;
397
398
  /* CFA data word (or data words when flex_p) must always be present.  */
399
5
  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
5
  if (flex_p)
404
2
    {
405
2
     if (sframe_fre->ra_loc != SFRAME_FRE_ELEM_LOC_NONE)
406
0
       fre_dataword_count += count;
407
2
     else if (sframe_fre->fp_loc != SFRAME_FRE_ELEM_LOC_NONE)
408
0
       fre_dataword_count += 1;
409
2
    }
410
3
  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
5
  if (sframe_fre->fp_loc != SFRAME_FRE_ELEM_LOC_NONE)
419
0
    fre_dataword_count += count;
420
421
5
  return fre_dataword_count;
422
5
}
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
5
{
431
5
  unsigned int max_dataword_size = 0;
432
5
  unsigned int cfa_offset_size = 0;
433
5
  unsigned int fp_offset_size = 0;
434
5
  unsigned int ra_offset_size = 0;
435
436
5
  unsigned int fre_dataword_size = 0;
437
438
  /* What size of data words appear in this frame row entry.  */
439
5
  cfa_offset_size = get_offset_size_in_bytes (sframe_fre->cfa_offset);
440
5
  if (sframe_fre->fp_loc == SFRAME_FRE_ELEM_LOC_STACK)
441
0
    fp_offset_size = get_offset_size_in_bytes (sframe_fre->fp_offset);
442
5
  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
5
  max_dataword_size = cfa_offset_size;
454
5
  if (fp_offset_size > max_dataword_size)
455
0
    max_dataword_size = fp_offset_size;
456
5
  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
5
  if (flex_p)
461
2
    {
462
2
      bool reg_p = (sframe_fre->cfa_base_reg != SFRAME_FRE_REG_INVALID);
463
2
      unsigned int data
464
2
  = SFRAME_V3_FLEX_FDE_CTRLWORD_ENCODE (sframe_fre->cfa_base_reg,
465
2
                sframe_fre->cfa_deref_p, reg_p);
466
2
      unsigned int cfa_control_word_size = get_udata_size_in_bytes (data);
467
2
      if (cfa_control_word_size > max_dataword_size)
468
0
  max_dataword_size = cfa_control_word_size;
469
470
2
      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
2
      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
2
    }
490
491
5
  gas_assert (max_dataword_size);
492
493
5
  switch (max_dataword_size)
494
5
    {
495
5
    case 1:
496
5
      fre_dataword_size = SFRAME_FRE_DATAWORD_1B;
497
5
      break;
498
0
    case 2:
499
0
      fre_dataword_size = SFRAME_FRE_DATAWORD_2B;
500
0
      break;
501
0
    case 4:
502
0
      fre_dataword_size = SFRAME_FRE_DATAWORD_4B;
503
0
      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
5
    }
509
510
5
  return fre_dataword_size;
511
5
}
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
5
{
531
  /* val expression stores the FDE start address offset from the start PC
532
     of function.  */
533
5
  expressionS val = {
534
5
    .X_op = O_subtract,
535
5
    .X_add_symbol = fre_pc_begin,
536
5
    .X_op_symbol = fde_start_address,
537
5
  };
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
5
  expressionS width = {
543
5
    .X_op = O_subtract,
544
5
    .X_add_symbol = fde_end_address,
545
5
    .X_op_symbol = fde_start_address,
546
5
  };
547
548
5
  *cexp = (expressionS) {
549
5
    .X_op = O_absent,
550
5
    .X_add_symbol = make_expr_symbol (&val),
551
5
    .X_op_symbol = make_expr_symbol (&width)
552
5
  };
553
5
}
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
3
{
573
3
  expressionS width = {
574
3
    .X_op = O_subtract,
575
3
    .X_add_symbol = dw_fde_end_addrS,
576
3
    .X_op_symbol = dw_fde_start_addrS
577
3
  };
578
579
3
  expressionS rest_of_func_info = {
580
3
    .X_op = O_constant,
581
3
    .X_add_number = func_info
582
3
  };
583
584
3
  *cexp = (expressionS) {
585
3
    .X_op = O_modulus,
586
3
    .X_add_symbol = make_expr_symbol (&rest_of_func_info),
587
3
    .X_op_symbol = make_expr_symbol (&width)
588
3
  };
589
3
}
590
591
static struct sframe_row_entry*
592
sframe_row_entry_new (void)
593
5
{
594
5
  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
5
  fre->cfa_base_reg = SFRAME_FRE_REG_INVALID;
598
5
  fre->fp_reg = SFRAME_FRE_REG_INVALID;
599
5
  fre->ra_reg = SFRAME_FRE_REG_INVALID;
600
5
  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
5
  fre->mangled_ra_p = false;
605
  /* Reset the RA undefined status by to zero by default.  */
606
5
  fre->ra_undefined_p = false;
607
608
5
  return fre;
609
5
}
610
611
static void
612
sframe_row_entry_free (struct sframe_row_entry *fre)
613
3
{
614
8
  while (fre)
615
5
    {
616
5
      struct sframe_row_entry *fre_next = fre->next;
617
5
      XDELETE (fre);
618
5
      fre = fre_next;
619
5
    }
620
3
}
621
622
/* Allocate an SFrame FDE.  */
623
624
static struct sframe_func_entry*
625
sframe_fde_alloc (void)
626
3
{
627
3
  return XCNEW (struct sframe_func_entry);
628
3
}
629
630
/* Free up the SFrame FDE.  */
631
632
static void
633
sframe_fde_free (struct sframe_func_entry *sframe_fde)
634
3
{
635
3
  if (sframe_fde == NULL)
636
0
    return;
637
638
3
  if (sframe_fde->sframe_fres)
639
3
    sframe_row_entry_free (sframe_fde->sframe_fres);
640
641
3
  XDELETE (sframe_fde);
642
3
}
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
5
{
653
5
  unsigned int fre_write_datawords = 0;
654
655
5
  unsigned int idx = sframe_fre_dataword_func_map_index (fre_dataword_size);
656
5
  gas_assert (idx < SFRAME_FRE_DATAWORD_FUNC_MAP_INDEX_MAX);
657
658
5
  if (sframe_fde->fde_flex_p)
659
2
    {
660
      /* SFrame FDE of type SFRAME_FDE_TYPE_FLEX.  */
661
      /* Output CFA related FRE data words.  */
662
2
      uint32_t reg = sframe_fre->cfa_base_reg;
663
2
      bool deref_p = sframe_fre->cfa_deref_p;
664
2
      uint32_t reg_data
665
2
  = SFRAME_V3_FLEX_FDE_CTRLWORD_ENCODE (reg, deref_p, 1 /* reg_p.  */);
666
2
      offsetT offset_data = sframe_fre->cfa_offset;
667
2
      dataword_func_map[idx].out_func (reg_data);
668
2
      dataword_func_map[idx].out_func (offset_data);
669
2
      fre_write_datawords += 2;
670
671
2
      bool reg_p = false;
672
2
      if (sframe_fre->ra_loc != SFRAME_FRE_ELEM_LOC_NONE)
673
0
  {
674
    /* Output RA related FRE data words.  */
675
0
    reg_p = sframe_fre->ra_loc == SFRAME_FRE_ELEM_LOC_REG;
676
0
    reg = reg_p ? sframe_fre->ra_reg : 0;
677
0
    deref_p = sframe_fre->ra_deref_p;
678
0
    reg_data = SFRAME_V3_FLEX_FDE_CTRLWORD_ENCODE (reg, deref_p, reg_p);
679
680
0
    offset_data = sframe_fre->ra_offset;
681
0
    dataword_func_map[idx].out_func (reg_data);
682
0
    dataword_func_map[idx].out_func (offset_data);
683
0
    fre_write_datawords += 2;
684
0
  }
685
2
      else if (sframe_fre->fp_loc != SFRAME_FRE_ELEM_LOC_NONE)
686
0
  {
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
0
    dataword_func_map[idx].out_func (SFRAME_FRE_RA_OFFSET_INVALID);
692
0
    fre_write_datawords += 1;
693
0
  }
694
695
2
      if (sframe_fre->fp_loc != SFRAME_FRE_ELEM_LOC_NONE)
696
0
  {
697
    /* Output FP related FRE data words.  */
698
0
    reg_p = sframe_fre->fp_loc == SFRAME_FRE_ELEM_LOC_REG;
699
0
    reg = reg_p ? sframe_fre->fp_reg : 0;
700
0
    deref_p = sframe_fre->fp_deref_p;
701
0
    reg_data = SFRAME_V3_FLEX_FDE_CTRLWORD_ENCODE (reg, deref_p, reg_p);
702
703
0
    offset_data = sframe_fre->fp_offset;
704
0
    dataword_func_map[idx].out_func (reg_data);
705
0
    dataword_func_map[idx].out_func (offset_data);
706
0
    fre_write_datawords += 2;
707
0
  }
708
2
    }
709
3
  else
710
3
    {
711
      /* SFrame FDE of type SFRAME_FDE_TYPE_DEFAULT.  */
712
      /* Output CFA related FRE data words.  */
713
3
      dataword_func_map[idx].out_func (sframe_fre->cfa_offset);
714
3
      fre_write_datawords++;
715
716
3
      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
3
      if (sframe_fre->fp_loc == SFRAME_FRE_ELEM_LOC_STACK)
732
0
  {
733
0
    dataword_func_map[idx].out_func (sframe_fre->fp_offset);
734
0
    fre_write_datawords++;
735
0
  }
736
3
    }
737
738
5
  return fre_write_datawords;
739
5
}
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
5
{
745
5
  unsigned char fre_info;
746
5
  unsigned int fre_dataword_count;
747
5
  unsigned int fre_dataword_size;
748
5
  unsigned int fre_base_reg;
749
5
  bool fre_mangled_ra_p;
750
5
  expressionS exp;
751
5
  unsigned int fre_addr_size;
752
753
5
  unsigned int fre_write_datawords = 0;
754
5
  symbolS *fde_start_addr = get_dw_fde_start_addrS (sframe_fde->dw_fde);
755
5
  symbolS *fde_end_addr = get_dw_fde_end_addrS (sframe_fde->dw_fde);
756
5
  bool flex_p = sframe_fde->fde_flex_p;
757
758
5
  fre_addr_size = 4; /* 4 bytes by default.   FIXME tie it to fre_type? */
759
760
  /* SFrame FRE Start Address.  */
761
5
  if (SFRAME_FRE_TYPE_SELECTION_OPT)
762
5
    {
763
5
      create_fre_start_addr_exp (&exp, sframe_fre->pc_begin, fde_start_addr,
764
5
         fde_end_addr);
765
5
      frag_grow (fre_addr_size);
766
5
      frag_var (rs_sframe, fre_addr_size, 0, 0,
767
5
    make_expr_symbol (&exp), 0, (char *) frag_now);
768
5
    }
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
5
  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
5
  else
791
5
    {
792
5
      fre_base_reg = get_fre_base_reg_id (sframe_fre);
793
5
      fre_dataword_count = get_fre_dataword_count (sframe_fre, flex_p);
794
5
      fre_dataword_size = sframe_get_fre_dataword_size (sframe_fre, flex_p);
795
5
      fre_mangled_ra_p = sframe_fre->mangled_ra_p;
796
5
    }
797
798
  /* Unused for flex FDE.  Set to zero.  */
799
5
  if (flex_p)
800
2
    fre_base_reg = 0;
801
802
5
  fre_info = sframe_set_fre_info (fre_base_reg, fre_dataword_count,
803
5
          fre_dataword_size, fre_mangled_ra_p);
804
5
  out_one (fre_info);
805
806
  /* Represent RA undefined as FRE without any data words.  */
807
5
  if (sframe_fre->ra_undefined_p)
808
0
    return;
809
810
5
  fre_write_datawords = output_sframe_row_entry_datawords (sframe_fde,
811
5
                 sframe_fre,
812
5
                 fre_dataword_size);
813
814
  /* Check if the expected number data words have been written out
815
     in this FRE.  */
816
5
  gas_assert (fre_write_datawords == fre_dataword_count);
817
5
}
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
3
{
824
3
  expressionS exp;
825
3
  symbolS *dw_fde_start_addrS, *dw_fde_end_addrS;
826
827
3
  dw_fde_start_addrS = get_dw_fde_start_addrS (sframe_fde->dw_fde);
828
3
  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
3
  exp.X_op = O_subtract;
833
3
  exp.X_add_symbol = dw_fde_start_addrS; /* to location.  */
834
3
  exp.X_op_symbol = symbol_temp_new_now (); /* from location.  */
835
3
  exp.X_add_number = 0;
836
3
  emit_expr (&exp, sizeof_member (sframe_func_desc_idx,
837
3
          sfdi_func_start_offset));
838
839
  /* Size of the function in bytes.  */
840
3
  exp.X_op = O_subtract;
841
3
  exp.X_add_symbol = dw_fde_end_addrS;
842
3
  exp.X_op_symbol = dw_fde_start_addrS;
843
3
  exp.X_add_number = 0;
844
3
  emit_expr (&exp, sizeof_member (sframe_func_desc_idx,
845
3
          sfdi_func_size));
846
847
  /* Offset to the function data (attribtues, FREs) in the FRE subsection.  */
848
3
  exp.X_op = O_subtract;
849
3
  exp.X_add_symbol = fre_symbol; /* Minuend.  */
850
3
  exp.X_op_symbol = start_of_fre_section; /* Subtrahend.  */
851
3
  exp.X_add_number = 0;
852
3
  emit_expr (&exp, sizeof_member (sframe_func_desc_idx,
853
3
          sfdi_func_start_fre_off));
854
3
}
855
856
static void
857
output_sframe_func_desc_attr (const struct sframe_func_entry *sframe_fde)
858
3
{
859
3
  symbolS *dw_fde_start_addrS, *dw_fde_end_addrS;
860
3
  unsigned int pauth_key;
861
3
  bool signal_p;
862
863
3
  dw_fde_start_addrS = get_dw_fde_start_addrS (sframe_fde->dw_fde);
864
3
  dw_fde_end_addrS = get_dw_fde_end_addrS (sframe_fde->dw_fde);
865
866
  /* Number of FREs must fit uint16_t.  */
867
3
  gas_assert (sframe_fde->num_fres <= UINT16_MAX);
868
3
  out_two (sframe_fde->num_fres);
869
870
  /* SFrame FDE function info.  */
871
3
  unsigned char func_info;
872
3
  pauth_key = (get_dw_fde_pauth_b_key_p (sframe_fde->dw_fde)
873
3
         ? SFRAME_AARCH64_PAUTH_KEY_B : SFRAME_AARCH64_PAUTH_KEY_A);
874
3
  signal_p = get_dw_fde_signal_p (sframe_fde->dw_fde);
875
3
  func_info = sframe_set_func_info (SFRAME_V3_FDE_PCTYPE_INC,
876
3
            SFRAME_FRE_TYPE_ADDR4,
877
3
            pauth_key, signal_p);
878
3
  if (SFRAME_FRE_TYPE_SELECTION_OPT)
879
3
    {
880
3
      expressionS cexp;
881
3
      create_func_info_exp (&cexp, dw_fde_end_addrS, dw_fde_start_addrS,
882
3
          func_info);
883
3
      frag_grow (1); /* Size of func info is unsigned char.  */
884
3
      frag_var (rs_sframe, 1, 0, 0, make_expr_symbol (&cexp), 0,
885
3
    (char *) frag_now);
886
3
    }
887
0
  else
888
0
    out_one (func_info);
889
890
3
  uint8_t finfo2 = 0;
891
3
  if (sframe_fde->fde_flex_p)
892
1
    finfo2 = SFRAME_V3_SET_FDE_TYPE (finfo2, SFRAME_FDE_TYPE_FLEX);
893
3
  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
3
  out_one (0);
898
3
}
899
900
static void
901
output_sframe_internal (void)
902
3
{
903
3
  expressionS exp;
904
3
  unsigned int i = 0;
905
906
3
  symbolS *end_of_frame_hdr;
907
3
  symbolS *end_of_frame_section;
908
3
  symbolS *start_of_func_desc_section;
909
3
  symbolS *start_of_fre_section;
910
3
  struct sframe_func_entry *sframe_fde, *sframe_fde_next;
911
3
  struct sframe_row_entry *sframe_fre;
912
3
  unsigned char abi_arch = 0;
913
3
  int fixed_fp_offset = SFRAME_CFA_FIXED_FP_INVALID;
914
3
  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
3
  unsigned char sframe_flags = SFRAME_F_FDE_FUNC_START_PCREL;
920
921
3
  unsigned int num_fdes = get_num_sframe_fdes ();
922
3
  unsigned int num_fres = get_num_sframe_fres ();
923
3
  symbolS **fde_fre_symbols = XNEWVEC (symbolS *, num_fdes);
924
6
  for (i = 0; i < num_fdes; i++)
925
3
    fde_fre_symbols[i] = symbol_temp_make ();
926
927
3
  end_of_frame_hdr = symbol_temp_make ();
928
3
  start_of_fre_section = symbol_temp_make ();
929
3
  start_of_func_desc_section = symbol_temp_make ();
930
3
  end_of_frame_section = symbol_temp_make ();
931
932
  /* Output the preamble of SFrame section.  */
933
3
  out_two (SFRAME_MAGIC);
934
3
  out_one (SFRAME_VERSION);
935
  /* gas must ensure emitted SFrame sections have at least the required flags
936
     set.  */
937
3
  gas_assert ((sframe_flags & SFRAME_V2_GNU_AS_LD_ENCODING_FLAGS)
938
3
        == SFRAME_V2_GNU_AS_LD_ENCODING_FLAGS);
939
3
  out_one (sframe_flags);
940
  /* abi/arch.  */
941
3
#ifdef sframe_get_abi_arch
942
3
  abi_arch = sframe_get_abi_arch ();
943
3
#endif
944
3
  gas_assert (abi_arch);
945
3
  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
3
  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
3
  if (!sframe_ra_tracking_p ())
960
3
    {
961
3
      fixed_ra_offset = sframe_cfa_ra_offset ();
962
3
      gas_assert (fixed_ra_offset != SFRAME_CFA_FIXED_RA_INVALID);
963
3
    }
964
3
  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
3
  out_one (0); /* Auxiliary SFrame header length.  */
970
971
3
  out_four (num_fdes); /* Number of FDEs.  */
972
3
  out_four (num_fres); /* Number of FREs.  */
973
974
  /* Size of FRE sub-section.  */
975
3
  exp.X_op = O_subtract;
976
3
  exp.X_add_symbol = end_of_frame_section;
977
3
  exp.X_op_symbol = start_of_fre_section;
978
3
  exp.X_add_number = 0;
979
3
  emit_expr (&exp, sizeof_member (sframe_header, sfh_fre_len));
980
981
  /* Offset of FDE sub-section.  */
982
3
  exp.X_op = O_subtract;
983
3
  exp.X_add_symbol = end_of_frame_hdr;
984
3
  exp.X_op_symbol = start_of_func_desc_section;
985
3
  exp.X_add_number = 0;
986
3
  emit_expr (&exp, sizeof_member (sframe_header, sfh_fdeoff));
987
988
  /* Offset of FRE sub-section.  */
989
3
  exp.X_op = O_subtract;
990
3
  exp.X_add_symbol = start_of_fre_section;
991
3
  exp.X_op_symbol = end_of_frame_hdr;
992
3
  exp.X_add_number = 0;
993
3
  emit_expr (&exp, sizeof_member (sframe_header, sfh_freoff));
994
995
3
  symbol_set_value_now (end_of_frame_hdr);
996
3
  symbol_set_value_now (start_of_func_desc_section);
997
998
  /* Output the SFrame function descriptor entries.  */
999
3
  i = 0;
1000
6
  for (sframe_fde = all_sframe_fdes; sframe_fde; sframe_fde = sframe_fde->next)
1001
3
    {
1002
3
      output_sframe_funcdesc_idx (start_of_fre_section, fde_fre_symbols[i],
1003
3
          sframe_fde);
1004
3
      i++;
1005
3
    }
1006
1007
3
  symbol_set_value_now (start_of_fre_section);
1008
1009
  /* Output the SFrame FREs.  */
1010
3
  i = 0;
1011
3
  sframe_fde = all_sframe_fdes;
1012
1013
6
  for (sframe_fde = all_sframe_fdes; sframe_fde; sframe_fde = sframe_fde_next)
1014
3
    {
1015
3
      symbol_set_value_now (fde_fre_symbols[i]);
1016
1017
3
      output_sframe_func_desc_attr (sframe_fde);
1018
1019
3
      for (sframe_fre = sframe_fde->sframe_fres;
1020
8
     sframe_fre;
1021
5
     sframe_fre = sframe_fre->next)
1022
5
  {
1023
5
    output_sframe_row_entry (sframe_fde, sframe_fre);
1024
5
  }
1025
3
      i++;
1026
3
      sframe_fde_next = sframe_fde->next;
1027
3
      sframe_fde_free (sframe_fde);
1028
3
    }
1029
3
  all_sframe_fdes = NULL;
1030
3
  last_sframe_fde = &all_sframe_fdes;
1031
1032
3
  symbol_set_value_now (end_of_frame_section);
1033
1034
3
  gas_assert (i == num_fdes);
1035
1036
3
  free (fde_fre_symbols);
1037
3
  fde_fre_symbols = NULL;
1038
3
}
1039
1040
static unsigned int
1041
get_num_sframe_fdes (void)
1042
3
{
1043
3
  struct sframe_func_entry *sframe_fde;
1044
3
  unsigned int total_fdes = 0;
1045
1046
6
  for (sframe_fde = all_sframe_fdes; sframe_fde ; sframe_fde = sframe_fde->next)
1047
3
    total_fdes++;
1048
1049
3
  return total_fdes;
1050
3
}
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
3
{
1057
3
  struct sframe_func_entry *sframe_fde;
1058
3
  unsigned int total_fres = 0;
1059
1060
6
  for (sframe_fde = all_sframe_fdes; sframe_fde ; sframe_fde = sframe_fde->next)
1061
3
    total_fres += sframe_fde->num_fres;
1062
1063
3
  return total_fres;
1064
3
}
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
3
{
1073
3
  struct sframe_xlate_ctx* xlate_ctx = XCNEW (struct sframe_xlate_ctx);
1074
3
  return xlate_ctx;
1075
3
}
1076
1077
/* Initialize the given SFrame translation context.  */
1078
1079
static void
1080
sframe_xlate_ctx_init (struct sframe_xlate_ctx *xlate_ctx)
1081
3
{
1082
3
  xlate_ctx->dw_fde = NULL;
1083
3
  xlate_ctx->flex_p = false;
1084
3
  xlate_ctx->first_fre = NULL;
1085
3
  xlate_ctx->last_fre = NULL;
1086
3
  xlate_ctx->cur_fre = NULL;
1087
3
  xlate_ctx->remember_fre = NULL;
1088
3
  xlate_ctx->num_xlate_fres = 0;
1089
3
}
1090
1091
/* Cleanup the given SFrame translation context.  */
1092
1093
static void
1094
sframe_xlate_ctx_cleanup (struct sframe_xlate_ctx *xlate_ctx)
1095
0
{
1096
0
  sframe_row_entry_free (xlate_ctx->first_fre);
1097
0
  XDELETE (xlate_ctx->remember_fre);
1098
0
  xlate_ctx->remember_fre = NULL;
1099
0
  XDELETE (xlate_ctx->cur_fre);
1100
0
  xlate_ctx->cur_fre = NULL;
1101
0
}
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
3
{
1109
3
  sframe_fde->dw_fde = xlate_ctx->dw_fde;
1110
3
  sframe_fde->fde_flex_p = xlate_ctx->flex_p;
1111
3
  sframe_fde->sframe_fres = xlate_ctx->first_fre;
1112
3
  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
3
  XDELETE (xlate_ctx->remember_fre);
1116
3
  xlate_ctx->remember_fre = NULL;
1117
3
}
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
0
{
1125
0
  gas_assert (xlate_ctx && xlate_ctx->cur_fre);
1126
1127
0
  return xlate_ctx->cur_fre->cfa_base_reg;
1128
0
}
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
5
{
1137
5
  gas_assert (xlate_ctx && fre);
1138
1139
  /* Add the frame row entry.  */
1140
5
  if (!xlate_ctx->first_fre)
1141
3
    xlate_ctx->first_fre = fre;
1142
2
  else if (xlate_ctx->last_fre)
1143
2
    xlate_ctx->last_fre->next = fre;
1144
1145
5
  xlate_ctx->last_fre = fre;
1146
1147
  /* Keep track of the total number of SFrame frame row entries.  */
1148
5
  xlate_ctx->num_xlate_fres++;
1149
5
}
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
2
{
1164
2
  gas_assert (prev_fre);
1165
2
  cur_fre->cfa_base_reg = prev_fre->cfa_base_reg;
1166
2
  cur_fre->cfa_offset = prev_fre->cfa_offset;
1167
2
  cur_fre->cfa_deref_p = prev_fre->cfa_deref_p;
1168
2
  cur_fre->fp_loc = prev_fre->fp_loc;
1169
2
  cur_fre->fp_reg = prev_fre->fp_reg;
1170
2
  cur_fre->fp_offset = prev_fre->fp_offset;
1171
2
  cur_fre->fp_deref_p = prev_fre->fp_deref_p;
1172
2
  cur_fre->ra_loc = prev_fre->ra_loc;
1173
2
  cur_fre->ra_reg = prev_fre->ra_reg;
1174
2
  cur_fre->ra_offset = prev_fre->ra_offset;
1175
2
  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
2
  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
2
  cur_fre->ra_undefined_p = prev_fre->ra_undefined_p;
1183
2
}
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
0
{
1190
0
  if (reg == SFRAME_CFA_SP_REG)
1191
0
    return "SP";
1192
0
  else if (reg == SFRAME_CFA_FP_REG)
1193
0
    return "FP";
1194
0
  else if (reg == SFRAME_CFA_RA_REG)
1195
0
    return "RA";
1196
0
  else
1197
0
    return NULL;
1198
0
}
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
4
{
1207
4
  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
4
  struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
1212
1213
4
  if (cur_fre)
1214
4
    {
1215
4
      if (!cur_fre->merge_candidate)
1216
2
  {
1217
2
    sframe_fre_set_end_addr (cur_fre, cfi_insn->u.ll.lab2);
1218
1219
2
    sframe_xlate_ctx_add_fre (xlate_ctx, cur_fre);
1220
2
    last_fre = xlate_ctx->last_fre;
1221
1222
2
    xlate_ctx->cur_fre = sframe_row_entry_new ();
1223
2
    cur_fre = xlate_ctx->cur_fre;
1224
1225
2
    if (last_fre)
1226
2
      sframe_row_entry_initialize (cur_fre, last_fre);
1227
2
  }
1228
2
      else
1229
2
  {
1230
2
    sframe_fre_set_end_addr (last_fre, cfi_insn->u.ll.lab2);
1231
2
    gas_assert (last_fre->merge_candidate == false);
1232
2
  }
1233
4
    }
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
4
  gas_assert (cur_fre);
1241
4
  sframe_fre_set_begin_addr (cur_fre, cfi_insn->u.ll.lab2);
1242
1243
4
  return SFRAME_XLATE_OK;
1244
4
}
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
4
{
1254
  /* Get the scratchpad FRE.  This FRE will eventually get linked in.  */
1255
4
  struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
1256
4
  if (!cur_fre)
1257
3
  {
1258
3
    xlate_ctx->cur_fre = sframe_row_entry_new ();
1259
3
    cur_fre = xlate_ctx->cur_fre;
1260
3
    sframe_fre_set_begin_addr (cur_fre,
1261
3
             get_dw_fde_start_addrS (xlate_ctx->dw_fde));
1262
3
  }
1263
1264
4
  offsetT offset = cfi_insn->u.ri.offset;
1265
4
  bool bound_p = sframe_fre_stack_offset_bound_p (offset, true);
1266
4
  if (!bound_p)
1267
0
    {
1268
0
      as_warn (_("no SFrame FDE emitted; "
1269
0
     ".cfi_def_cfa with unsupported offset value"));
1270
0
      return SFRAME_XLATE_ERR_NOTREPRESENTED;
1271
0
    }
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
4
  if (cfi_insn->u.ri.reg != SFRAME_CFA_SP_REG
1285
1
      && cfi_insn->u.ri.reg != SFRAME_CFA_FP_REG)
1286
1
    {
1287
1
      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
1
      else
1295
1
  xlate_ctx->flex_p = true;
1296
1
    }
1297
1298
4
  sframe_fre_set_cfa_base_reg (cur_fre, cfi_insn->u.ri.reg);
1299
4
  sframe_fre_set_cfa_offset (cur_fre, cfi_insn->u.ri.offset);
1300
4
  cur_fre->merge_candidate = false;
1301
4
  cur_fre->cfa_deref_p = false;
1302
1303
4
  return SFRAME_XLATE_OK;
1304
4
}
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
0
{
1313
0
  const struct sframe_row_entry *last_fre = xlate_ctx->last_fre;
1314
  /* Get the scratchpad FRE.  This FRE will eventually get linked in.  */
1315
0
  struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
1316
1317
0
  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
0
  if (cfi_insn->u.r != SFRAME_CFA_SP_REG
1322
0
      && cfi_insn->u.r != SFRAME_CFA_FP_REG)
1323
0
    {
1324
0
      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
0
      else
1332
  /* Currently, SFRAME_FDE_TYPE_FLEX is generated for AMD64 only.  */
1333
0
  xlate_ctx->flex_p = true;
1334
0
    }
1335
1336
0
  sframe_fre_set_cfa_base_reg (cur_fre, cfi_insn->u.r);
1337
0
  if (last_fre)
1338
0
    sframe_fre_set_cfa_offset (cur_fre, sframe_fre_get_cfa_offset (last_fre));
1339
0
  cur_fre->cfa_deref_p = false;
1340
1341
0
  cur_fre->merge_candidate = false;
1342
1343
0
  return SFRAME_XLATE_OK;
1344
0
}
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
0
{
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
0
  struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
1357
0
  unsigned int cur_cfa_reg = sframe_xlate_ctx_get_cur_cfa_reg (xlate_ctx);
1358
1359
0
  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
0
  if (cur_cfa_reg == SFRAME_CFA_FP_REG || cur_cfa_reg == SFRAME_CFA_SP_REG)
1364
0
    {
1365
0
      if (sframe_fre_stack_offset_bound_p (cfi_insn->u.i, true))
1366
0
  {
1367
0
    sframe_fre_set_cfa_offset (cur_fre, cfi_insn->u.i);
1368
0
    cur_fre->merge_candidate = false;
1369
0
  }
1370
0
      else
1371
0
  {
1372
0
    as_warn (_("no SFrame FDE emitted; "
1373
0
         ".cfi_def_cfa_offset with unsupported offset value"));
1374
0
    return SFRAME_XLATE_ERR_NOTREPRESENTED;
1375
0
  }
1376
0
    }
1377
0
  else
1378
0
    {
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
0
      as_warn (_("no SFrame FDE emitted; "
1382
0
     ".cfi_def_cfa_offset without CFA base register in effect"));
1383
0
      return SFRAME_XLATE_ERR_NOTREPRESENTED;
1384
0
    }
1385
1386
0
  return SFRAME_XLATE_OK;
1387
0
}
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
6
{
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
6
  struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
1400
6
  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
6
  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
6
  if (cfi_insn->u.ri.reg == SFRAME_CFA_FP_REG)
1419
0
    {
1420
0
      sframe_fre_set_fp_track (cur_fre, cfi_insn->u.ri.offset);
1421
0
      cur_fre->fp_reg = SFRAME_FRE_REG_INVALID;
1422
0
      cur_fre->fp_deref_p = true;
1423
0
      cur_fre->merge_candidate = false;
1424
0
    }
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
6
  else if (cfi_insn->u.ri.reg == SFRAME_CFA_RA_REG)
1430
3
    {
1431
3
      if (!sframe_ra_tracking_p ()
1432
3
    && cfi_insn->u.ri.offset == sframe_cfa_ra_offset ())
1433
3
  {
1434
    /* Reset RA tracking info, if fixed offset.  */
1435
3
    cur_fre->ra_reg = SFRAME_FRE_REG_INVALID;
1436
3
    cur_fre->ra_loc = SFRAME_FRE_ELEM_LOC_NONE;
1437
3
    cur_fre->ra_deref_p = false;
1438
3
    cur_fre->merge_candidate = false;
1439
3
  }
1440
0
      else
1441
0
  {
1442
0
    sframe_fre_set_ra_track (cur_fre, cfi_insn->u.ri.offset);
1443
0
    cur_fre->ra_reg = SFRAME_FRE_REG_INVALID;
1444
0
    cur_fre->ra_loc = SFRAME_FRE_ELEM_LOC_STACK;
1445
0
    cur_fre->ra_deref_p = true;
1446
0
    cur_fre->merge_candidate = false;
1447
1448
0
    if (!sframe_ra_tracking_p () && sframe_support_flex_fde_p ())
1449
0
      xlate_ctx->flex_p = true;
1450
0
  }
1451
3
    }
1452
1453
  /* Skip all other registers.  */
1454
6
  return SFRAME_XLATE_OK;
1455
6
}
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
0
{
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
0
  if (cfi_insn->u.ri.reg == SFRAME_CFA_FP_REG
1473
0
      || (sframe_ra_tracking_p () && cfi_insn->u.ri.reg == SFRAME_CFA_RA_REG)
1474
      /* Ignore SP reg, if offset matches assumed default rule.  */
1475
0
      || (cfi_insn->u.ri.reg == SFRAME_CFA_SP_REG
1476
0
    && ((sframe_get_abi_arch () != SFRAME_ABI_S390X_ENDIAN_BIG
1477
0
         && cfi_insn->u.ri.offset != 0)
1478
0
        || (sframe_get_abi_arch () == SFRAME_ABI_S390X_ENDIAN_BIG
1479
0
      && cfi_insn->u.ri.offset != SFRAME_S390X_SP_VAL_OFFSET))))
1480
0
    {
1481
0
      as_warn (_("no SFrame FDE emitted; %s with %s reg %u"),
1482
0
         cfi_esc_p ? ".cfi_escape DW_CFA_val_offset" : ".cfi_val_offset",
1483
0
         sframe_register_name (cfi_insn->u.ri.reg), cfi_insn->u.ri.reg);
1484
0
      return SFRAME_XLATE_ERR_NOTREPRESENTED; /* Not represented.  */
1485
0
    }
1486
1487
  /* Safe to skip.  */
1488
0
  return SFRAME_XLATE_OK;
1489
0
}
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
0
{
1506
0
  if (sframe_support_flex_fde_p ())
1507
0
    {
1508
0
      struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
1509
1510
0
      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
0
      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
0
    }
1533
1534
0
  if (cfi_insn->u.rr.reg1 == SFRAME_CFA_RA_REG
1535
      /* SFrame does not track SP explicitly.  */
1536
0
      || (cfi_insn->u.rr.reg1 == SFRAME_CFA_SP_REG
1537
0
    && sframe_get_abi_arch () != SFRAME_ABI_S390X_ENDIAN_BIG)
1538
0
      || 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
0
  return SFRAME_XLATE_OK;
1547
0
}
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
0
{
1603
0
  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
0
  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
0
  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
0
  if (cfi_insn->u.r == SFRAME_CFA_FP_REG)
1622
0
    {
1623
0
      gas_assert (cur_fre);
1624
0
      cur_fre->fp_loc = cie_fre->fp_loc;
1625
0
      cur_fre->fp_offset = cie_fre->fp_offset;
1626
0
      cur_fre->merge_candidate = false;
1627
0
    }
1628
0
  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
0
  return SFRAME_XLATE_OK;
1638
0
}
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
1
{
2090
1
  const struct cfi_escape_data *e;
2091
1
  bool warn_p = false;
2092
1
  int err = SFRAME_XLATE_OK;
2093
1
  offsetT firstop;
2094
2095
1
  e = cfi_insn->u.esc;
2096
2097
1
  if (!e)
2098
0
    return SFRAME_XLATE_ERR_INVAL;
2099
2100
1
  if (e->exp.X_op != O_constant
2101
1
      || e->type != CFI_ESC_byte
2102
1
      || e->reloc != TC_PARSE_CONS_RETURN_NONE)
2103
0
    return SFRAME_XLATE_ERR_NOTREPRESENTED;
2104
2105
1
  firstop = e->exp.X_add_number;
2106
1
  switch (firstop)
2107
1
    {
2108
1
    case DW_CFA_nop:
2109
      /* One or more nops together are harmless for SFrame.  */
2110
1
      while (e->next)
2111
0
  {
2112
0
    e = e->next;
2113
0
    if (e->exp.X_op != O_constant || e->exp.X_add_number != DW_CFA_nop
2114
0
        || e->type != CFI_ESC_byte
2115
0
        || e->reloc != TC_PARSE_CONS_RETURN_NONE)
2116
0
      {
2117
0
        warn_p = true;
2118
0
        break;
2119
0
      }
2120
0
  }
2121
1
      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
1
    }
2143
2144
1
  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
1
  return err;
2156
1
}
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
3
{
2177
3
  if (cfi_insn->u.r == SFRAME_CFA_FP_REG
2178
3
      || 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
3
  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
3
  return SFRAME_XLATE_OK;
2197
3
}
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
0
{
2237
0
  struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
2238
2239
0
  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
0
  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
0
  return SFRAME_XLATE_OK;
2255
0
}
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
0
{
2263
0
  const char *cfi_name;
2264
2265
0
  switch (cfi_opc)
2266
0
    {
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
0
      case CFI_val_encoded_addr:
2285
0
  cfi_name = "CFI_val_encoded_addr";
2286
0
  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
0
    }
2293
2294
0
  return cfi_name;
2295
0
}
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
18
{
2307
18
  int err = 0;
2308
2309
  /* Atleast one cfi_insn per FDE is expected.  */
2310
18
  gas_assert (cfi_insn);
2311
18
  int op = cfi_insn->insn;
2312
2313
18
  switch (op)
2314
18
    {
2315
4
    case DW_CFA_advance_loc:
2316
4
      err = sframe_xlate_do_advance_loc (xlate_ctx, cfi_insn);
2317
4
      break;
2318
4
    case DW_CFA_def_cfa:
2319
4
      err = sframe_xlate_do_def_cfa (xlate_ctx, cfi_insn);
2320
4
      break;
2321
0
    case DW_CFA_def_cfa_register:
2322
0
      err = sframe_xlate_do_def_cfa_register (xlate_ctx, cfi_insn);
2323
0
      break;
2324
0
    case DW_CFA_def_cfa_offset:
2325
0
      err = sframe_xlate_do_def_cfa_offset (xlate_ctx, cfi_insn);
2326
0
      break;
2327
6
    case DW_CFA_offset:
2328
6
      err = sframe_xlate_do_offset (xlate_ctx, cfi_insn);
2329
6
      break;
2330
0
    case DW_CFA_val_offset:
2331
0
      err = sframe_xlate_do_val_offset (xlate_ctx, cfi_insn, false);
2332
0
      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
0
    case DW_CFA_restore:
2340
0
      err = sframe_xlate_do_restore (xlate_ctx, cfi_insn);
2341
0
      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
0
    case DW_CFA_register:
2351
0
      err = sframe_xlate_do_register (xlate_ctx, cfi_insn);
2352
0
      break;
2353
1
    case CFI_escape:
2354
1
      err = sframe_xlate_do_cfi_escape (xlate_ctx, cfi_insn);
2355
1
      break;
2356
3
    case DW_CFA_undefined:
2357
3
      err = sframe_xlate_do_cfi_undefined (xlate_ctx, cfi_insn);
2358
3
      break;
2359
0
    case DW_CFA_same_value:
2360
0
      err = sframe_xlate_do_same_value (xlate_ctx, cfi_insn);
2361
0
      break;
2362
0
    default:
2363
      /* Other skipped operations may, however, impact the asynchronicity.  */
2364
0
      {
2365
0
  const char *cfi_name = sframe_get_cfi_name (op);
2366
2367
0
  if (!cfi_name)
2368
0
    cfi_name = _("(unknown)");
2369
0
  as_warn (_("no SFrame FDE emitted; CFI insn %s (%#x)"),
2370
0
     cfi_name, op);
2371
0
  err = SFRAME_XLATE_ERR_NOTREPRESENTED;
2372
0
      }
2373
18
    }
2374
2375
  /* Any error will cause no SFrame FDE later.  The user has already been
2376
     warned.  */
2377
18
  return err;
2378
18
}
2379
2380
2381
static int
2382
sframe_do_fde (struct sframe_xlate_ctx *xlate_ctx,
2383
         const struct fde_entry *dw_fde)
2384
3
{
2385
3
  const struct cfi_insn_data *cfi_insn;
2386
3
  int err = SFRAME_XLATE_OK;
2387
2388
3
  xlate_ctx->dw_fde = dw_fde;
2389
2390
  /* SFrame format cannot represent a non-default DWARF return column reg.  */
2391
3
  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
21
  for (cfi_insn = dw_fde->data; cfi_insn; cfi_insn = cfi_insn->next)
2400
18
    {
2401
      /* Translate each CFI, and buffer the state in translation context.  */
2402
18
      err = sframe_do_cfi_insn (xlate_ctx, cfi_insn);
2403
18
      if (err != SFRAME_XLATE_OK)
2404
0
  {
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
0
    return err; /* Return the error code.  */
2409
0
  }
2410
18
    }
2411
2412
  /* Link in the scratchpad FRE that the last few CFI insns helped create.  */
2413
3
  if (xlate_ctx->cur_fre)
2414
3
    {
2415
3
      sframe_xlate_ctx_add_fre (xlate_ctx, xlate_ctx->cur_fre);
2416
3
      xlate_ctx->cur_fre = NULL;
2417
3
    }
2418
  /* Designate the end of the last SFrame FRE.  */
2419
3
  if (xlate_ctx->last_fre)
2420
3
    {
2421
3
      xlate_ctx->last_fre->pc_end
2422
3
  = get_dw_fde_end_addrS (xlate_ctx->dw_fde);
2423
3
    }
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
3
  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
3
  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
3
  return SFRAME_XLATE_OK;
2459
3
}
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
3
{
2470
3
  struct fde_entry *dw_fde = NULL;
2471
3
  struct sframe_func_entry *sframe_fde = NULL;
2472
2473
3
  struct sframe_xlate_ctx *xlate_ctx = sframe_xlate_ctx_alloc ();
2474
2475
6
  for (dw_fde = all_fde_data; dw_fde ; dw_fde = dw_fde->next)
2476
3
    {
2477
3
      sframe_fde = sframe_fde_alloc ();
2478
      /* Initialize the translation context with information anew.  */
2479
3
      sframe_xlate_ctx_init (xlate_ctx);
2480
2481
      /* Process and link SFrame FDEs if no error.  */
2482
3
      int err = sframe_do_fde (xlate_ctx, dw_fde);
2483
3
      if (err && get_dw_fde_signal_p (dw_fde))
2484
0
  {
2485
0
    sframe_xlate_ctx_cleanup (xlate_ctx);
2486
0
    xlate_ctx->flex_p = false;
2487
0
    err = SFRAME_XLATE_OK;
2488
0
  }
2489
2490
3
      if (err)
2491
0
  {
2492
0
    sframe_xlate_ctx_cleanup (xlate_ctx);
2493
0
    sframe_fde_free (sframe_fde);
2494
0
  }
2495
3
      else
2496
3
  {
2497
    /* All done.  Transfer the state from the SFrame translation
2498
       context to the SFrame FDE.  */
2499
3
    sframe_xlate_ctx_finalize (xlate_ctx, sframe_fde);
2500
3
    *last_sframe_fde = sframe_fde;
2501
3
    last_sframe_fde = &sframe_fde->next;
2502
3
  }
2503
3
    }
2504
2505
3
  XDELETE (xlate_ctx);
2506
3
}
2507
2508
void
2509
output_sframe (segT sframe_seg)
2510
3
{
2511
3
  (void) sframe_seg;
2512
2513
  /* Currently only SFRAME_VERSION_3 can be emitted.  */
2514
3
  gas_assert (flag_gen_sframe_version == GEN_SFRAME_VERSION_3);
2515
  /* Setup the version specific access functions.  */
2516
3
  sframe_set_version (flag_gen_sframe_version);
2517
2518
  /* Process all fdes and create SFrame stack trace information.  */
2519
3
  create_sframe_all ();
2520
2521
3
  output_sframe_internal ();
2522
3
}
2523
2524
#else  /*  support_sframe_p  */
2525
2526
void
2527
output_sframe (segT sframe_seg ATTRIBUTE_UNUSED)
2528
{
2529
}
2530
2531
#endif /*  support_sframe_p  */