Coverage Report

Created: 2026-05-11 07:54

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