Coverage Report

Created: 2026-04-04 08:16

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
69
# 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
31
# 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
135
{
74
135
  FRAG_APPEND_1_CHAR (byte);
75
135
}
76
77
/* Emit a two-byte word into the current segment.  */
78
79
static inline void
80
out_two (int data)
81
25
{
82
25
  md_number_to_chars (frag_more (2), data, 2);
83
25
}
84
85
/* Emit a four byte word into the current segment.  */
86
87
static inline void
88
out_four (int data)
89
22
{
90
22
  md_number_to_chars (frag_more (4), data, 4);
91
22
}
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
57
{
98
57
  return dw_fde->start_address;
99
57
}
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
55
{
106
55
  return dw_fde->end_address;
107
55
}
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
12
{
113
#ifdef tc_fde_entry_extras
114
  return (dw_fde->pauth_key == AARCH64_PAUTH_KEY_B);
115
#else
116
12
  return false;
117
12
#endif
118
12
}
119
120
/* Get whether signal frame.  */
121
static bool
122
get_dw_fde_signal_p (const struct fde_entry *dw_fde)
123
14
{
124
14
  return (dw_fde->signal_frame == 1);
125
14
}
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
26
{
132
26
  fre->pc_begin = beginS;
133
26
}
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
25
{
145
25
  fre->cfa_base_reg = cfa_base_reg;
146
25
  fre->merge_candidate = false;
147
25
}
148
149
static offsetT
150
sframe_fre_get_cfa_offset (const struct sframe_row_entry * fre)
151
8
{
152
8
  offsetT offset = fre->cfa_offset;
153
154
  /* For s390x undo adjustment of CFA offset (to enable 8-bit offsets).  */
155
8
  if (sframe_get_abi_arch () == SFRAME_ABI_S390X_ENDIAN_BIG)
156
0
    offset = SFRAME_V2_S390X_CFA_OFFSET_DECODE (offset);
157
158
8
  return offset;
159
8
}
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
15
{
172
  /* For s390x, CFA offset is adjusted to enable 8-bit offsets.  */
173
15
  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
15
  return (offset >= INT32_MIN && offset <= INT32_MAX);
177
15
}
178
179
static void
180
sframe_fre_set_cfa_offset (struct sframe_row_entry *fre,
181
         offsetT cfa_offset)
182
23
{
183
  /* For s390x adjust CFA offset to enable 8-bit offsets.  */
184
23
  if (sframe_get_abi_arch () == SFRAME_ABI_S390X_ENDIAN_BIG)
185
0
    cfa_offset = SFRAME_V2_S390X_CFA_OFFSET_ENCODE (cfa_offset);
186
187
23
  fre->cfa_offset = cfa_offset;
188
23
  fre->merge_candidate = false;
189
23
}
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
19
{
213
19
  unsigned int size = 0;
214
215
19
  if (value == (int8_t)value)
216
18
    size = 1;
217
1
  else if (value == (int16_t)value)
218
1
    size = 2;
219
0
  else if (value == (int32_t)value)
220
0
    size = 4;
221
0
  else
222
0
    return 8;
223
224
19
  return size;
225
19
}
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
9
{
232
9
  unsigned int size = 0;
233
234
9
  if (value <= UINT8_MAX)
235
9
    size = 1;
236
0
  else if (value <= UINT16_MAX)
237
0
    size = 2;
238
0
  else
239
0
    size = 4;
240
241
9
  return size;
242
9
}
243
18
#define SFRAME_FRE_DATAWORD_FUNC_MAP_INDEX_1B  0 /* SFRAME_FRE_DATAWORD_1B.  */
244
1
#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
19
#define SFRAME_FRE_DATAWORD_FUNC_MAP_INDEX_8B  3 /* Not supported in SFrame.  */
247
#define SFRAME_FRE_DATAWORD_FUNC_MAP_INDEX_MAX \
248
19
  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
19
{
263
19
  unsigned int idx = SFRAME_FRE_DATAWORD_FUNC_MAP_INDEX_MAX;
264
265
19
  switch (dataword_size)
266
19
    {
267
18
      case SFRAME_FRE_DATAWORD_1B:
268
18
  idx = SFRAME_FRE_DATAWORD_FUNC_MAP_INDEX_1B;
269
18
  break;
270
1
      case SFRAME_FRE_DATAWORD_2B:
271
1
  idx = SFRAME_FRE_DATAWORD_FUNC_MAP_INDEX_2B;
272
1
  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
19
    }
280
281
19
  return idx;
282
19
}
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
19
{
306
19
  unsigned char fre_info;
307
19
  fre_info = SFRAME_V1_FRE_INFO (cfa_base_reg, dataword_count, dataword_size);
308
19
  fre_info = SFRAME_V1_FRE_INFO_UPDATE_MANGLED_RA_P (mangled_ra_p, fre_info);
309
19
  return fre_info;
310
19
}
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
12
{
318
12
  unsigned char func_info;
319
12
  func_info = SFRAME_V3_FDE_FUNC_INFO (fde_pc_type, fre_type);
320
12
  func_info = SFRAME_V3_FDE_UPDATE_PAUTH_KEY (pauth_key, func_info);
321
12
  func_info = SFRAME_V3_FDE_UPDATE_SIGNAL_P (signal_p, func_info);
322
12
  return func_info;
323
12
}
324
325
/* SFrame version specific operations setup.  */
326
327
static void
328
sframe_set_version (enum gen_sframe_version flag_ver)
329
11
{
330
11
  if (flag_ver == GEN_SFRAME_VERSION_3)
331
11
    {
332
11
      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
11
      sframe_ver_ops.set_fre_info = sframe_v1_set_fre_info;
337
11
      sframe_ver_ops.set_func_info = sframe_v3_set_func_info;
338
11
    }
339
11
}
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
19
{
347
19
  return sframe_ver_ops.set_fre_info (cfa_base_reg, dataword_count,
348
19
              dataword_size, mangled_ra_p);
349
19
}
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
12
{
357
12
  return sframe_ver_ops.set_func_info (fde_type, fre_type, pauth_key,
358
12
               signal_p);
359
12
}
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
19
{
376
19
  unsigned int cfi_insn_cfa_base_reg = sframe_fre->cfa_base_reg;
377
19
  unsigned fre_base_reg = SFRAME_BASE_REG_SP;
378
379
19
  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
19
  gas_assert (fre_base_reg == SFRAME_BASE_REG_SP
384
19
        || fre_base_reg == SFRAME_BASE_REG_FP);
385
386
19
  return fre_base_reg;
387
19
}
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
19
{
394
  /* For SFRAME_FDE_TYPE_FLEX FDE type, each entity (CFA, FP, RA) may carry up
395
     to two data words.  */
396
19
  unsigned int count = flex_p ? 2 : 1;
397
398
  /* CFA data word (or data words when flex_p) must always be present.  */
399
19
  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
19
  if (flex_p)
404
9
    {
405
9
     if (sframe_fre->ra_loc != SFRAME_FRE_ELEM_LOC_NONE)
406
0
       fre_dataword_count += count;
407
9
     else if (sframe_fre->fp_loc != SFRAME_FRE_ELEM_LOC_NONE)
408
0
       fre_dataword_count += 1;
409
9
    }
410
10
  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
19
  if (sframe_fre->fp_loc != SFRAME_FRE_ELEM_LOC_NONE)
419
0
    fre_dataword_count += count;
420
421
19
  return fre_dataword_count;
422
19
}
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
19
{
431
19
  unsigned int max_dataword_size = 0;
432
19
  unsigned int cfa_offset_size = 0;
433
19
  unsigned int fp_offset_size = 0;
434
19
  unsigned int ra_offset_size = 0;
435
436
19
  unsigned int fre_dataword_size = 0;
437
438
  /* What size of data words appear in this frame row entry.  */
439
19
  cfa_offset_size = get_offset_size_in_bytes (sframe_fre->cfa_offset);
440
19
  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
19
  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
19
  max_dataword_size = cfa_offset_size;
454
19
  if (fp_offset_size > max_dataword_size)
455
0
    max_dataword_size = fp_offset_size;
456
19
  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
19
  if (flex_p)
461
9
    {
462
9
      bool reg_p = (sframe_fre->cfa_base_reg != SFRAME_FRE_REG_INVALID);
463
9
      unsigned int data
464
9
  = SFRAME_V3_FLEX_FDE_CTRLWORD_ENCODE (sframe_fre->cfa_base_reg,
465
9
                sframe_fre->cfa_deref_p, reg_p);
466
9
      unsigned int cfa_control_word_size = get_udata_size_in_bytes (data);
467
9
      if (cfa_control_word_size > max_dataword_size)
468
0
  max_dataword_size = cfa_control_word_size;
469
470
9
      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
9
      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
9
    }
490
491
19
  gas_assert (max_dataword_size);
492
493
19
  switch (max_dataword_size)
494
19
    {
495
18
    case 1:
496
18
      fre_dataword_size = SFRAME_FRE_DATAWORD_1B;
497
18
      break;
498
1
    case 2:
499
1
      fre_dataword_size = SFRAME_FRE_DATAWORD_2B;
500
1
      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
19
    }
509
510
19
  return fre_dataword_size;
511
19
}
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
19
{
531
  /* val expression stores the FDE start address offset from the start PC
532
     of function.  */
533
19
  expressionS val = {
534
19
    .X_op = O_subtract,
535
19
    .X_add_symbol = fre_pc_begin,
536
19
    .X_op_symbol = fde_start_address,
537
19
  };
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
19
  expressionS width = {
543
19
    .X_op = O_subtract,
544
19
    .X_add_symbol = fde_end_address,
545
19
    .X_op_symbol = fde_start_address,
546
19
  };
547
548
19
  *cexp = (expressionS) {
549
19
    .X_op = O_absent,
550
19
    .X_add_symbol = make_expr_symbol (&val),
551
19
    .X_op_symbol = make_expr_symbol (&width)
552
19
  };
553
19
}
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
12
{
573
12
  expressionS width = {
574
12
    .X_op = O_subtract,
575
12
    .X_add_symbol = dw_fde_end_addrS,
576
12
    .X_op_symbol = dw_fde_start_addrS
577
12
  };
578
579
12
  expressionS rest_of_func_info = {
580
12
    .X_op = O_constant,
581
12
    .X_add_number = func_info
582
12
  };
583
584
12
  *cexp = (expressionS) {
585
12
    .X_op = O_modulus,
586
12
    .X_add_symbol = make_expr_symbol (&rest_of_func_info),
587
12
    .X_op_symbol = make_expr_symbol (&width)
588
12
  };
589
12
}
590
591
static struct sframe_row_entry*
592
sframe_row_entry_new (void)
593
22
{
594
22
  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
22
  fre->cfa_base_reg = SFRAME_FRE_REG_INVALID;
598
22
  fre->fp_reg = SFRAME_FRE_REG_INVALID;
599
22
  fre->ra_reg = SFRAME_FRE_REG_INVALID;
600
22
  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
22
  fre->mangled_ra_p = false;
605
  /* Reset the RA undefined status by to zero by default.  */
606
22
  fre->ra_undefined_p = false;
607
608
22
  return fre;
609
22
}
610
611
static void
612
sframe_row_entry_free (struct sframe_row_entry *fre)
613
14
{
614
34
  while (fre)
615
20
    {
616
20
      struct sframe_row_entry *fre_next = fre->next;
617
20
      XDELETE (fre);
618
20
      fre = fre_next;
619
20
    }
620
14
}
621
622
/* Allocate an SFrame FDE.  */
623
624
static struct sframe_func_entry*
625
sframe_fde_alloc (void)
626
14
{
627
14
  return XCNEW (struct sframe_func_entry);
628
14
}
629
630
/* Free up the SFrame FDE.  */
631
632
static void
633
sframe_fde_free (struct sframe_func_entry *sframe_fde)
634
14
{
635
14
  if (sframe_fde == NULL)
636
0
    return;
637
638
14
  if (sframe_fde->sframe_fres)
639
12
    sframe_row_entry_free (sframe_fde->sframe_fres);
640
641
14
  XDELETE (sframe_fde);
642
14
}
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
19
{
653
19
  unsigned int fre_write_datawords = 0;
654
655
19
  unsigned int idx = sframe_fre_dataword_func_map_index (fre_dataword_size);
656
19
  gas_assert (idx < SFRAME_FRE_DATAWORD_FUNC_MAP_INDEX_MAX);
657
658
19
  if (sframe_fde->fde_flex_p)
659
9
    {
660
      /* SFrame FDE of type SFRAME_FDE_TYPE_FLEX.  */
661
      /* Output CFA related FRE data words.  */
662
9
      uint32_t reg = sframe_fre->cfa_base_reg;
663
9
      bool deref_p = sframe_fre->cfa_deref_p;
664
9
      uint32_t reg_data
665
9
  = SFRAME_V3_FLEX_FDE_CTRLWORD_ENCODE (reg, deref_p, 1 /* reg_p.  */);
666
9
      offsetT offset_data = sframe_fre->cfa_offset;
667
9
      dataword_func_map[idx].out_func (reg_data);
668
9
      dataword_func_map[idx].out_func (offset_data);
669
9
      fre_write_datawords += 2;
670
671
9
      bool reg_p = false;
672
9
      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
9
      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
9
      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
9
    }
709
10
  else
710
10
    {
711
      /* SFrame FDE of type SFRAME_FDE_TYPE_DEFAULT.  */
712
      /* Output CFA related FRE data words.  */
713
10
      dataword_func_map[idx].out_func (sframe_fre->cfa_offset);
714
10
      fre_write_datawords++;
715
716
10
      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
10
      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
10
    }
737
738
19
  return fre_write_datawords;
739
19
}
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
19
{
745
19
  unsigned char fre_info;
746
19
  unsigned int fre_dataword_count;
747
19
  unsigned int fre_dataword_size;
748
19
  unsigned int fre_base_reg;
749
19
  bool fre_mangled_ra_p;
750
19
  expressionS exp;
751
19
  unsigned int fre_addr_size;
752
753
19
  unsigned int fre_write_datawords = 0;
754
19
  symbolS *fde_start_addr = get_dw_fde_start_addrS (sframe_fde->dw_fde);
755
19
  symbolS *fde_end_addr = get_dw_fde_end_addrS (sframe_fde->dw_fde);
756
19
  bool flex_p = sframe_fde->fde_flex_p;
757
758
19
  fre_addr_size = 4; /* 4 bytes by default.   FIXME tie it to fre_type? */
759
760
  /* SFrame FRE Start Address.  */
761
19
  if (SFRAME_FRE_TYPE_SELECTION_OPT)
762
19
    {
763
19
      create_fre_start_addr_exp (&exp, sframe_fre->pc_begin, fde_start_addr,
764
19
         fde_end_addr);
765
19
      frag_grow (fre_addr_size);
766
19
      frag_var (rs_sframe, fre_addr_size, 0, 0,
767
19
    make_expr_symbol (&exp), 0, (char *) frag_now);
768
19
    }
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
19
  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
19
  else
791
19
    {
792
19
      fre_base_reg = get_fre_base_reg_id (sframe_fre);
793
19
      fre_dataword_count = get_fre_dataword_count (sframe_fre, flex_p);
794
19
      fre_dataword_size = sframe_get_fre_dataword_size (sframe_fre, flex_p);
795
19
      fre_mangled_ra_p = sframe_fre->mangled_ra_p;
796
19
    }
797
798
  /* Unused for flex FDE.  Set to zero.  */
799
19
  if (flex_p)
800
9
    fre_base_reg = 0;
801
802
19
  fre_info = sframe_set_fre_info (fre_base_reg, fre_dataword_count,
803
19
          fre_dataword_size, fre_mangled_ra_p);
804
19
  out_one (fre_info);
805
806
  /* Represent RA undefined as FRE without any data words.  */
807
19
  if (sframe_fre->ra_undefined_p)
808
0
    return;
809
810
19
  fre_write_datawords = output_sframe_row_entry_datawords (sframe_fde,
811
19
                 sframe_fre,
812
19
                 fre_dataword_size);
813
814
  /* Check if the expected number data words have been written out
815
     in this FRE.  */
816
19
  gas_assert (fre_write_datawords == fre_dataword_count);
817
19
}
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
12
{
824
12
  expressionS exp;
825
12
  symbolS *dw_fde_start_addrS, *dw_fde_end_addrS;
826
827
12
  dw_fde_start_addrS = get_dw_fde_start_addrS (sframe_fde->dw_fde);
828
12
  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
12
  exp.X_op = O_subtract;
833
12
  exp.X_add_symbol = dw_fde_start_addrS; /* to location.  */
834
12
  exp.X_op_symbol = symbol_temp_new_now (); /* from location.  */
835
12
  exp.X_add_number = 0;
836
12
  emit_expr (&exp, sizeof_member (sframe_func_desc_idx,
837
12
          sfdi_func_start_offset));
838
839
  /* Size of the function in bytes.  */
840
12
  exp.X_op = O_subtract;
841
12
  exp.X_add_symbol = dw_fde_end_addrS;
842
12
  exp.X_op_symbol = dw_fde_start_addrS;
843
12
  exp.X_add_number = 0;
844
12
  emit_expr (&exp, sizeof_member (sframe_func_desc_idx,
845
12
          sfdi_func_size));
846
847
  /* Offset to the function data (attribtues, FREs) in the FRE subsection.  */
848
12
  exp.X_op = O_subtract;
849
12
  exp.X_add_symbol = fre_symbol; /* Minuend.  */
850
12
  exp.X_op_symbol = start_of_fre_section; /* Subtrahend.  */
851
12
  exp.X_add_number = 0;
852
12
  emit_expr (&exp, sizeof_member (sframe_func_desc_idx,
853
12
          sfdi_func_start_fre_off));
854
12
}
855
856
static void
857
output_sframe_func_desc_attr (const struct sframe_func_entry *sframe_fde)
858
12
{
859
12
  symbolS *dw_fde_start_addrS, *dw_fde_end_addrS;
860
12
  unsigned int pauth_key;
861
12
  bool signal_p;
862
863
12
  dw_fde_start_addrS = get_dw_fde_start_addrS (sframe_fde->dw_fde);
864
12
  dw_fde_end_addrS = get_dw_fde_end_addrS (sframe_fde->dw_fde);
865
866
  /* Number of FREs must fit uint16_t.  */
867
12
  gas_assert (sframe_fde->num_fres <= UINT16_MAX);
868
12
  out_two (sframe_fde->num_fres);
869
870
  /* SFrame FDE function info.  */
871
12
  unsigned char func_info;
872
12
  pauth_key = (get_dw_fde_pauth_b_key_p (sframe_fde->dw_fde)
873
12
         ? SFRAME_AARCH64_PAUTH_KEY_B : SFRAME_AARCH64_PAUTH_KEY_A);
874
12
  signal_p = get_dw_fde_signal_p (sframe_fde->dw_fde);
875
12
  func_info = sframe_set_func_info (SFRAME_V3_FDE_PCTYPE_INC,
876
12
            SFRAME_FRE_TYPE_ADDR4,
877
12
            pauth_key, signal_p);
878
12
  if (SFRAME_FRE_TYPE_SELECTION_OPT)
879
12
    {
880
12
      expressionS cexp;
881
12
      create_func_info_exp (&cexp, dw_fde_end_addrS, dw_fde_start_addrS,
882
12
          func_info);
883
12
      frag_grow (1); /* Size of func info is unsigned char.  */
884
12
      frag_var (rs_sframe, 1, 0, 0, make_expr_symbol (&cexp), 0,
885
12
    (char *) frag_now);
886
12
    }
887
0
  else
888
0
    out_one (func_info);
889
890
12
  uint8_t finfo2 = 0;
891
12
  if (sframe_fde->fde_flex_p)
892
4
    finfo2 = SFRAME_V3_SET_FDE_TYPE (finfo2, SFRAME_FDE_TYPE_FLEX);
893
12
  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
12
  out_one (0);
898
12
}
899
900
static void
901
output_sframe_internal (void)
902
11
{
903
11
  expressionS exp;
904
11
  unsigned int i = 0;
905
906
11
  symbolS *end_of_frame_hdr;
907
11
  symbolS *end_of_frame_section;
908
11
  symbolS *start_of_func_desc_section;
909
11
  symbolS *start_of_fre_section;
910
11
  struct sframe_func_entry *sframe_fde, *sframe_fde_next;
911
11
  struct sframe_row_entry *sframe_fre;
912
11
  unsigned char abi_arch = 0;
913
11
  int fixed_fp_offset = SFRAME_CFA_FIXED_FP_INVALID;
914
11
  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
11
  unsigned char sframe_flags = SFRAME_F_FDE_FUNC_START_PCREL;
920
921
11
  unsigned int num_fdes = get_num_sframe_fdes ();
922
11
  unsigned int num_fres = get_num_sframe_fres ();
923
11
  symbolS **fde_fre_symbols = XNEWVEC (symbolS *, num_fdes);
924
23
  for (i = 0; i < num_fdes; i++)
925
12
    fde_fre_symbols[i] = symbol_temp_make ();
926
927
11
  end_of_frame_hdr = symbol_temp_make ();
928
11
  start_of_fre_section = symbol_temp_make ();
929
11
  start_of_func_desc_section = symbol_temp_make ();
930
11
  end_of_frame_section = symbol_temp_make ();
931
932
  /* Output the preamble of SFrame section.  */
933
11
  out_two (SFRAME_MAGIC);
934
11
  out_one (SFRAME_VERSION);
935
  /* gas must ensure emitted SFrame sections have at least the required flags
936
     set.  */
937
11
  gas_assert ((sframe_flags & SFRAME_V2_GNU_AS_LD_ENCODING_FLAGS)
938
11
        == SFRAME_V2_GNU_AS_LD_ENCODING_FLAGS);
939
11
  out_one (sframe_flags);
940
  /* abi/arch.  */
941
11
#ifdef sframe_get_abi_arch
942
11
  abi_arch = sframe_get_abi_arch ();
943
11
#endif
944
11
  gas_assert (abi_arch);
945
11
  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
11
  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
11
  if (!sframe_ra_tracking_p ())
960
11
    {
961
11
      fixed_ra_offset = sframe_cfa_ra_offset ();
962
11
      gas_assert (fixed_ra_offset != SFRAME_CFA_FIXED_RA_INVALID);
963
11
    }
964
11
  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
11
  out_one (0); /* Auxiliary SFrame header length.  */
970
971
11
  out_four (num_fdes); /* Number of FDEs.  */
972
11
  out_four (num_fres); /* Number of FREs.  */
973
974
  /* Size of FRE sub-section.  */
975
11
  exp.X_op = O_subtract;
976
11
  exp.X_add_symbol = end_of_frame_section;
977
11
  exp.X_op_symbol = start_of_fre_section;
978
11
  exp.X_add_number = 0;
979
11
  emit_expr (&exp, sizeof_member (sframe_header, sfh_fre_len));
980
981
  /* Offset of FDE sub-section.  */
982
11
  exp.X_op = O_subtract;
983
11
  exp.X_add_symbol = end_of_frame_hdr;
984
11
  exp.X_op_symbol = start_of_func_desc_section;
985
11
  exp.X_add_number = 0;
986
11
  emit_expr (&exp, sizeof_member (sframe_header, sfh_fdeoff));
987
988
  /* Offset of FRE sub-section.  */
989
11
  exp.X_op = O_subtract;
990
11
  exp.X_add_symbol = start_of_fre_section;
991
11
  exp.X_op_symbol = end_of_frame_hdr;
992
11
  exp.X_add_number = 0;
993
11
  emit_expr (&exp, sizeof_member (sframe_header, sfh_freoff));
994
995
11
  symbol_set_value_now (end_of_frame_hdr);
996
11
  symbol_set_value_now (start_of_func_desc_section);
997
998
  /* Output the SFrame function descriptor entries.  */
999
11
  i = 0;
1000
23
  for (sframe_fde = all_sframe_fdes; sframe_fde; sframe_fde = sframe_fde->next)
1001
12
    {
1002
12
      output_sframe_funcdesc_idx (start_of_fre_section, fde_fre_symbols[i],
1003
12
          sframe_fde);
1004
12
      i++;
1005
12
    }
1006
1007
11
  symbol_set_value_now (start_of_fre_section);
1008
1009
  /* Output the SFrame FREs.  */
1010
11
  i = 0;
1011
11
  sframe_fde = all_sframe_fdes;
1012
1013
23
  for (sframe_fde = all_sframe_fdes; sframe_fde; sframe_fde = sframe_fde_next)
1014
12
    {
1015
12
      symbol_set_value_now (fde_fre_symbols[i]);
1016
1017
12
      output_sframe_func_desc_attr (sframe_fde);
1018
1019
12
      for (sframe_fre = sframe_fde->sframe_fres;
1020
31
     sframe_fre;
1021
19
     sframe_fre = sframe_fre->next)
1022
19
  {
1023
19
    output_sframe_row_entry (sframe_fde, sframe_fre);
1024
19
  }
1025
12
      i++;
1026
12
      sframe_fde_next = sframe_fde->next;
1027
12
      sframe_fde_free (sframe_fde);
1028
12
    }
1029
11
  all_sframe_fdes = NULL;
1030
11
  last_sframe_fde = &all_sframe_fdes;
1031
1032
11
  symbol_set_value_now (end_of_frame_section);
1033
1034
11
  gas_assert (i == num_fdes);
1035
1036
11
  free (fde_fre_symbols);
1037
11
  fde_fre_symbols = NULL;
1038
11
}
1039
1040
static unsigned int
1041
get_num_sframe_fdes (void)
1042
11
{
1043
11
  struct sframe_func_entry *sframe_fde;
1044
11
  unsigned int total_fdes = 0;
1045
1046
23
  for (sframe_fde = all_sframe_fdes; sframe_fde ; sframe_fde = sframe_fde->next)
1047
12
    total_fdes++;
1048
1049
11
  return total_fdes;
1050
11
}
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
11
{
1057
11
  struct sframe_func_entry *sframe_fde;
1058
11
  unsigned int total_fres = 0;
1059
1060
23
  for (sframe_fde = all_sframe_fdes; sframe_fde ; sframe_fde = sframe_fde->next)
1061
12
    total_fres += sframe_fde->num_fres;
1062
1063
11
  return total_fres;
1064
11
}
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
11
{
1073
11
  struct sframe_xlate_ctx* xlate_ctx = XCNEW (struct sframe_xlate_ctx);
1074
11
  return xlate_ctx;
1075
11
}
1076
1077
/* Initialize the given SFrame translation context.  */
1078
1079
static void
1080
sframe_xlate_ctx_init (struct sframe_xlate_ctx *xlate_ctx)
1081
14
{
1082
14
  xlate_ctx->dw_fde = NULL;
1083
14
  xlate_ctx->flex_p = false;
1084
14
  xlate_ctx->first_fre = NULL;
1085
14
  xlate_ctx->last_fre = NULL;
1086
14
  xlate_ctx->cur_fre = NULL;
1087
14
  xlate_ctx->remember_fre = NULL;
1088
14
  xlate_ctx->num_xlate_fres = 0;
1089
14
}
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
12
{
1109
12
  sframe_fde->dw_fde = xlate_ctx->dw_fde;
1110
12
  sframe_fde->fde_flex_p = xlate_ctx->flex_p;
1111
12
  sframe_fde->sframe_fres = xlate_ctx->first_fre;
1112
12
  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
12
  XDELETE (xlate_ctx->remember_fre);
1116
12
  xlate_ctx->remember_fre = NULL;
1117
12
}
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
20
{
1137
20
  gas_assert (xlate_ctx && fre);
1138
1139
  /* Add the frame row entry.  */
1140
20
  if (!xlate_ctx->first_fre)
1141
13
    xlate_ctx->first_fre = fre;
1142
7
  else if (xlate_ctx->last_fre)
1143
7
    xlate_ctx->last_fre->next = fre;
1144
1145
20
  xlate_ctx->last_fre = fre;
1146
1147
  /* Keep track of the total number of SFrame frame row entries.  */
1148
20
  xlate_ctx->num_xlate_fres++;
1149
20
}
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
8
{
1164
8
  gas_assert (prev_fre);
1165
8
  cur_fre->cfa_base_reg = prev_fre->cfa_base_reg;
1166
8
  cur_fre->cfa_offset = prev_fre->cfa_offset;
1167
8
  cur_fre->cfa_deref_p = prev_fre->cfa_deref_p;
1168
8
  cur_fre->fp_loc = prev_fre->fp_loc;
1169
8
  cur_fre->fp_reg = prev_fre->fp_reg;
1170
8
  cur_fre->fp_offset = prev_fre->fp_offset;
1171
8
  cur_fre->fp_deref_p = prev_fre->fp_deref_p;
1172
8
  cur_fre->ra_loc = prev_fre->ra_loc;
1173
8
  cur_fre->ra_reg = prev_fre->ra_reg;
1174
8
  cur_fre->ra_offset = prev_fre->ra_offset;
1175
8
  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
8
  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
8
  cur_fre->ra_undefined_p = prev_fre->ra_undefined_p;
1183
8
}
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
12
{
1207
12
  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
12
  struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
1212
1213
12
  if (cur_fre)
1214
12
    {
1215
12
      if (!cur_fre->merge_candidate)
1216
8
  {
1217
8
    sframe_fre_set_end_addr (cur_fre, cfi_insn->u.ll.lab2);
1218
1219
8
    sframe_xlate_ctx_add_fre (xlate_ctx, cur_fre);
1220
8
    last_fre = xlate_ctx->last_fre;
1221
1222
8
    xlate_ctx->cur_fre = sframe_row_entry_new ();
1223
8
    cur_fre = xlate_ctx->cur_fre;
1224
1225
8
    if (last_fre)
1226
8
      sframe_row_entry_initialize (cur_fre, last_fre);
1227
8
  }
1228
4
      else
1229
4
  {
1230
4
    sframe_fre_set_end_addr (last_fre, cfi_insn->u.ll.lab2);
1231
4
    gas_assert (last_fre->merge_candidate == false);
1232
4
  }
1233
12
    }
1234
0
  else
1235
0
    {
1236
0
      xlate_ctx->cur_fre = sframe_row_entry_new ();
1237
0
      cur_fre = xlate_ctx->cur_fre;
1238
0
    }
1239
1240
12
  gas_assert (cur_fre);
1241
12
  sframe_fre_set_begin_addr (cur_fre, cfi_insn->u.ll.lab2);
1242
1243
12
  return SFRAME_XLATE_OK;
1244
12
}
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
15
{
1254
  /* Get the scratchpad FRE.  This FRE will eventually get linked in.  */
1255
15
  struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
1256
15
  if (!cur_fre)
1257
14
  {
1258
14
    xlate_ctx->cur_fre = sframe_row_entry_new ();
1259
14
    cur_fre = xlate_ctx->cur_fre;
1260
14
    sframe_fre_set_begin_addr (cur_fre,
1261
14
             get_dw_fde_start_addrS (xlate_ctx->dw_fde));
1262
14
  }
1263
1264
15
  offsetT offset = cfi_insn->u.ri.offset;
1265
15
  bool bound_p = sframe_fre_stack_offset_bound_p (offset, true);
1266
15
  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
15
  if (cfi_insn->u.ri.reg != SFRAME_CFA_SP_REG
1285
1
      && cfi_insn->u.ri.reg != SFRAME_CFA_FP_REG)
1286
1
    {
1287
1
      if (!sframe_support_flex_fde_p ())
1288
0
  {
1289
0
    as_warn (_("no SFrame FDE emitted; "
1290
0
         "non-SP/FP register %u in .cfi_def_cfa"),
1291
0
       cfi_insn->u.ri.reg);
1292
0
    return SFRAME_XLATE_ERR_NOTREPRESENTED;
1293
0
  }
1294
1
      else
1295
1
  xlate_ctx->flex_p = true;
1296
1
    }
1297
1298
15
  sframe_fre_set_cfa_base_reg (cur_fre, cfi_insn->u.ri.reg);
1299
15
  sframe_fre_set_cfa_offset (cur_fre, cfi_insn->u.ri.offset);
1300
15
  cur_fre->merge_candidate = false;
1301
15
  cur_fre->cfa_deref_p = false;
1302
1303
15
  return SFRAME_XLATE_OK;
1304
15
}
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
10
{
1313
10
  const struct sframe_row_entry *last_fre = xlate_ctx->last_fre;
1314
  /* Get the scratchpad FRE.  This FRE will eventually get linked in.  */
1315
10
  struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
1316
1317
10
  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
10
  if (cfi_insn->u.r != SFRAME_CFA_SP_REG
1322
10
      && cfi_insn->u.r != SFRAME_CFA_FP_REG)
1323
10
    {
1324
10
      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
10
      else
1332
  /* Currently, SFRAME_FDE_TYPE_FLEX is generated for AMD64 only.  */
1333
10
  xlate_ctx->flex_p = true;
1334
10
    }
1335
1336
10
  sframe_fre_set_cfa_base_reg (cur_fre, cfi_insn->u.r);
1337
10
  if (last_fre)
1338
8
    sframe_fre_set_cfa_offset (cur_fre, sframe_fre_get_cfa_offset (last_fre));
1339
10
  cur_fre->cfa_deref_p = false;
1340
1341
10
  cur_fre->merge_candidate = false;
1342
1343
10
  return SFRAME_XLATE_OK;
1344
10
}
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
29
{
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
29
  struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
1400
29
  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
29
  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
29
  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
29
  else if (cfi_insn->u.ri.reg == SFRAME_CFA_RA_REG)
1430
14
    {
1431
14
      if (!sframe_ra_tracking_p ()
1432
14
    && cfi_insn->u.ri.offset == sframe_cfa_ra_offset ())
1433
14
  {
1434
    /* Reset RA tracking info, if fixed offset.  */
1435
14
    cur_fre->ra_reg = SFRAME_FRE_REG_INVALID;
1436
14
    cur_fre->ra_loc = SFRAME_FRE_ELEM_LOC_NONE;
1437
14
    cur_fre->ra_deref_p = false;
1438
14
    cur_fre->merge_candidate = false;
1439
14
  }
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
14
    }
1452
1453
  /* Skip all other registers.  */
1454
29
  return SFRAME_XLATE_OK;
1455
29
}
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
2
{
1506
2
  if (sframe_support_flex_fde_p ())
1507
2
    {
1508
2
      struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
1509
1510
2
      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
2
      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
2
    }
1533
1534
2
  if (cfi_insn->u.rr.reg1 == SFRAME_CFA_RA_REG
1535
      /* SFrame does not track SP explicitly.  */
1536
2
      || (cfi_insn->u.rr.reg1 == SFRAME_CFA_SP_REG
1537
0
    && sframe_get_abi_arch () != SFRAME_ABI_S390X_ENDIAN_BIG)
1538
2
      || 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
2
  return SFRAME_XLATE_OK;
1547
2
}
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
8
{
1603
8
  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
8
  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
8
  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
8
  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
8
  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
8
  return SFRAME_XLATE_OK;
1638
8
}
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
8
{
2090
8
  const struct cfi_escape_data *e;
2091
8
  bool warn_p = false;
2092
8
  int err = SFRAME_XLATE_OK;
2093
8
  offsetT firstop;
2094
2095
8
  e = cfi_insn->u.esc;
2096
2097
8
  if (!e)
2098
0
    return SFRAME_XLATE_ERR_INVAL;
2099
2100
8
  if (e->exp.X_op != O_constant
2101
8
      || e->type != CFI_ESC_byte
2102
8
      || e->reloc != TC_PARSE_CONS_RETURN_NONE)
2103
0
    return SFRAME_XLATE_ERR_NOTREPRESENTED;
2104
2105
8
  firstop = e->exp.X_add_number;
2106
8
  switch (firstop)
2107
8
    {
2108
8
    case DW_CFA_nop:
2109
      /* One or more nops together are harmless for SFrame.  */
2110
9
      while (e->next)
2111
2
  {
2112
2
    e = e->next;
2113
2
    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
1
      {
2117
1
        warn_p = true;
2118
1
        break;
2119
1
      }
2120
2
  }
2121
8
      break;
2122
2123
0
    case DW_CFA_def_cfa_expression:
2124
0
      err = sframe_xlate_do_escape_cfa_expr (xlate_ctx, cfi_insn, &warn_p);
2125
0
      break;
2126
2127
0
    case DW_CFA_expression:
2128
0
      err = sframe_xlate_do_escape_expr (xlate_ctx, cfi_insn, &warn_p);
2129
0
      break;
2130
2131
0
    case DW_CFA_val_offset:
2132
0
      err = sframe_xlate_do_escape_val_offset (xlate_ctx, cfi_insn, &warn_p);
2133
0
      break;
2134
2135
0
    case DW_CFA_GNU_args_size:
2136
0
      err = sframe_xlate_do_escape_gnu_args_size (xlate_ctx, cfi_insn, &warn_p);
2137
0
      break;
2138
2139
0
    default:
2140
0
      warn_p = true;
2141
0
      break;
2142
8
    }
2143
2144
8
  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
8
  return err;
2156
8
}
2157
2158
/* Translate DW_CFA_undefined into SFrame context.
2159
2160
   DW_CFA_undefined op indicates that from now on, the previous value of
2161
   register can’t be restored anymore.  In DWARF, for the return address (RA)
2162
   register, this indicates to an unwinder that there is no return address
2163
   and the unwind is complete.
2164
2165
   In SFrame, represent the use of the RA register with DW_CFA_undefined as
2166
   SFrame FRE without any trailing FRE data words.  Stack tracers can use this
2167
   as indication that an outermost frame has been reached and the stack trace
2168
   is complete.  The use of other registers of interest with  DW_CFA_undefined
2169
   cannot be represented in SFrame.  Therefore skip generating an SFrame FDE.
2170
2171
   Return SFRAME_XLATE_OK if success.  */
2172
2173
static int
2174
sframe_xlate_do_cfi_undefined (const struct sframe_xlate_ctx *xlate_ctx ATTRIBUTE_UNUSED,
2175
             const struct cfi_insn_data *cfi_insn)
2176
3
{
2177
3
  if (cfi_insn->u.r == SFRAME_CFA_FP_REG
2178
3
      || cfi_insn->u.r == SFRAME_CFA_SP_REG)
2179
0
    {
2180
0
      as_warn (_("no SFrame FDE emitted; %s reg %u in .cfi_undefined"),
2181
0
         sframe_register_name (cfi_insn->u.r), cfi_insn->u.r);
2182
0
      return SFRAME_XLATE_ERR_NOTREPRESENTED; /* Not represented.  */
2183
0
    }
2184
3
  else if (cfi_insn->u.r == SFRAME_CFA_RA_REG)
2185
0
    {
2186
      /* Represent RA undefined (i.e. outermost frame) as FRE without any
2187
   data words.  */
2188
0
      struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
2189
2190
0
      gas_assert (cur_fre);
2191
      /* Set RA undefined status bit.  */
2192
0
      cur_fre->ra_undefined_p = true;
2193
0
      cur_fre->merge_candidate = false;
2194
0
    }
2195
2196
3
  return SFRAME_XLATE_OK;
2197
3
}
2198
2199
/* Translate DW_CFA_same_value into SFrame context.
2200
2201
   DW_CFA_same_value op indicates that current value of register is the same as
2202
   in the previous frame, i.e. no restoration needed.  In SFrame stack trace
2203
   format, the handling is done similar to DW_CFA_restore.
2204
2205
   For SFRAME_CFA_RA_REG, if RA-tracking is enabled, reset the SFrame FRE state
2206
   for REG_RA to indicate that register does not need restoration.  P.S.: Even
2207
   though resetting just REG_RA may be contradicting the AArch64 ABI (as Frame
2208
   Record contains for FP and LR), sframe_xlate_do_same_value () does not
2209
   detect the case and assumes the users' DW_CFA_same_value SFRAME_CFA_RA_REG
2210
   has a sound reason.  For ABIs, where RA-tracking is disabled, handle it
2211
   similar to DW_CFA_restore: ignore the directive, it is safe to skip.  The
2212
   reasoning is similar to that for DW_CFA_restore: if such a restoration was
2213
   meant to be of any consequence, there must have been the necessary CFI
2214
   directives for updating the CFA rule too such that the recovered RA from
2215
   stack is valid.
2216
2217
   SFrame based stacktracers will implement CFA-based SP recovery for all ABIs:
2218
   SP for previous frame is based on the applicable CFA-rule.  There is no
2219
   representation in SFrame to indicate "no restoration needed" for REG_SP,
2220
   when going to the previous frame.  That said, if DW_CFA_same_value is seen
2221
   for SFRAME_CFA_SP_REG, handle it similar to DW_CFA_restore: ignore the
2222
   directive, it is safe to skip.  The reasoning is similar to that for
2223
   DW_CFA_restore: if such a restoration was meant to be of any consequence,
2224
   there must have been the necessary CFI directives for updating the CFA rule
2225
   too.  The latter will be duly processed by the SFrame generation code, as
2226
   expected.
2227
2228
   For SFRAME_CFA_FP_REG, reset the state of the current FRE to indicate that
2229
   the value is the same as previous frame.
2230
2231
   Return SFRAME_XLATE_OK if success.  */
2232
2233
static int
2234
sframe_xlate_do_same_value (const struct sframe_xlate_ctx *xlate_ctx,
2235
          const struct cfi_insn_data *cfi_insn)
2236
0
{
2237
0
  struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
2238
2239
0
  if (sframe_ra_tracking_p () && cfi_insn->u.r == SFRAME_CFA_RA_REG)
2240
0
    {
2241
0
      cur_fre->ra_loc = SFRAME_FRE_ELEM_LOC_NONE;
2242
0
      cur_fre->ra_offset = 0;
2243
0
      cur_fre->ra_undefined_p = false;
2244
0
      cur_fre->merge_candidate = false;
2245
0
    }
2246
0
  else if (cfi_insn->u.r == SFRAME_CFA_FP_REG)
2247
0
    {
2248
0
      cur_fre->fp_loc = SFRAME_FRE_ELEM_LOC_NONE;
2249
0
      cur_fre->fp_offset = 0;
2250
0
      cur_fre->merge_candidate = false;
2251
0
    }
2252
2253
  /* Safe to skip.  */
2254
0
  return SFRAME_XLATE_OK;
2255
0
}
2256
2257
/* Returns the DWARF call frame instruction name or fake CFI name for the
2258
   specified CFI opcode, or NULL if the value is not recognized.  */
2259
2260
static const char *
2261
sframe_get_cfi_name (int cfi_opc)
2262
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
88
{
2307
88
  int err = 0;
2308
2309
  /* Atleast one cfi_insn per FDE is expected.  */
2310
88
  gas_assert (cfi_insn);
2311
88
  int op = cfi_insn->insn;
2312
2313
88
  switch (op)
2314
88
    {
2315
12
    case DW_CFA_advance_loc:
2316
12
      err = sframe_xlate_do_advance_loc (xlate_ctx, cfi_insn);
2317
12
      break;
2318
15
    case DW_CFA_def_cfa:
2319
15
      err = sframe_xlate_do_def_cfa (xlate_ctx, cfi_insn);
2320
15
      break;
2321
10
    case DW_CFA_def_cfa_register:
2322
10
      err = sframe_xlate_do_def_cfa_register (xlate_ctx, cfi_insn);
2323
10
      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
29
    case DW_CFA_offset:
2328
29
      err = sframe_xlate_do_offset (xlate_ctx, cfi_insn);
2329
29
      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
8
    case DW_CFA_restore:
2340
8
      err = sframe_xlate_do_restore (xlate_ctx, cfi_insn);
2341
8
      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
2
    case DW_CFA_register:
2351
2
      err = sframe_xlate_do_register (xlate_ctx, cfi_insn);
2352
2
      break;
2353
8
    case CFI_escape:
2354
8
      err = sframe_xlate_do_cfi_escape (xlate_ctx, cfi_insn);
2355
8
      break;
2356
3
    case DW_CFA_undefined:
2357
3
      err = sframe_xlate_do_cfi_undefined (xlate_ctx, cfi_insn);
2358
3
      break;
2359
0
    case DW_CFA_same_value:
2360
0
      err = sframe_xlate_do_same_value (xlate_ctx, cfi_insn);
2361
0
      break;
2362
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
88
    }
2374
2375
  /* Any error will cause no SFrame FDE later.  The user has already been
2376
     warned.  */
2377
88
  return err;
2378
88
}
2379
2380
2381
static int
2382
sframe_do_fde (struct sframe_xlate_ctx *xlate_ctx,
2383
         const struct fde_entry *dw_fde)
2384
14
{
2385
14
  const struct cfi_insn_data *cfi_insn;
2386
14
  int err = SFRAME_XLATE_OK;
2387
2388
14
  xlate_ctx->dw_fde = dw_fde;
2389
2390
  /* SFrame format cannot represent a non-default DWARF return column reg.  */
2391
14
  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
100
  for (cfi_insn = dw_fde->data; cfi_insn; cfi_insn = cfi_insn->next)
2400
88
    {
2401
      /* Translate each CFI, and buffer the state in translation context.  */
2402
88
      err = sframe_do_cfi_insn (xlate_ctx, cfi_insn);
2403
88
      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
88
    }
2411
2412
  /* Link in the scratchpad FRE that the last few CFI insns helped create.  */
2413
12
  if (xlate_ctx->cur_fre)
2414
12
    {
2415
12
      sframe_xlate_ctx_add_fre (xlate_ctx, xlate_ctx->cur_fre);
2416
12
      xlate_ctx->cur_fre = NULL;
2417
12
    }
2418
  /* Designate the end of the last SFrame FRE.  */
2419
12
  if (xlate_ctx->last_fre)
2420
12
    {
2421
12
      xlate_ctx->last_fre->pc_end
2422
12
  = get_dw_fde_end_addrS (xlate_ctx->dw_fde);
2423
12
    }
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
12
  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
12
  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
12
  return SFRAME_XLATE_OK;
2459
12
}
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
11
{
2470
11
  struct fde_entry *dw_fde = NULL;
2471
11
  struct sframe_func_entry *sframe_fde = NULL;
2472
2473
11
  struct sframe_xlate_ctx *xlate_ctx = sframe_xlate_ctx_alloc ();
2474
2475
25
  for (dw_fde = all_fde_data; dw_fde ; dw_fde = dw_fde->next)
2476
14
    {
2477
14
      sframe_fde = sframe_fde_alloc ();
2478
      /* Initialize the translation context with information anew.  */
2479
14
      sframe_xlate_ctx_init (xlate_ctx);
2480
2481
      /* Process and link SFrame FDEs if no error.  */
2482
14
      int err = sframe_do_fde (xlate_ctx, dw_fde);
2483
14
      if (err && get_dw_fde_signal_p (dw_fde))
2484
0
  {
2485
0
    sframe_xlate_ctx_cleanup (xlate_ctx);
2486
0
    xlate_ctx->flex_p = false;
2487
0
    err = SFRAME_XLATE_OK;
2488
0
  }
2489
2490
14
      if (err)
2491
2
  {
2492
2
    sframe_xlate_ctx_cleanup (xlate_ctx);
2493
2
    sframe_fde_free (sframe_fde);
2494
2
  }
2495
12
      else
2496
12
  {
2497
    /* All done.  Transfer the state from the SFrame translation
2498
       context to the SFrame FDE.  */
2499
12
    sframe_xlate_ctx_finalize (xlate_ctx, sframe_fde);
2500
12
    *last_sframe_fde = sframe_fde;
2501
12
    last_sframe_fde = &sframe_fde->next;
2502
12
  }
2503
14
    }
2504
2505
11
  XDELETE (xlate_ctx);
2506
11
}
2507
2508
void
2509
output_sframe (segT sframe_seg)
2510
11
{
2511
11
  (void) sframe_seg;
2512
2513
  /* Currently only SFRAME_VERSION_3 can be emitted.  */
2514
11
  gas_assert (flag_gen_sframe_version == GEN_SFRAME_VERSION_3);
2515
  /* Setup the version specific access functions.  */
2516
11
  sframe_set_version (flag_gen_sframe_version);
2517
2518
  /* Process all fdes and create SFrame stack trace information.  */
2519
11
  create_sframe_all ();
2520
2521
11
  output_sframe_internal ();
2522
11
}
2523
2524
#else  /*  support_sframe_p  */
2525
2526
void
2527
output_sframe (segT sframe_seg ATTRIBUTE_UNUSED)
2528
{
2529
}
2530
2531
#endif /*  support_sframe_p  */