Coverage Report

Created: 2026-09-14 08:07

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