gen-sframe.c revision 1.1.1.2 1 /* gen-sframe.c - Support for generating SFrame section.
2 Copyright (C) 2022-2025 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
28 #ifdef support_sframe_p
29
30 #ifndef sizeof_member
31 # define sizeof_member(type, member) (sizeof (((type *)0)->member))
32 #endif
33
34 /* SFrame FRE type selection optimization is an optimization for size.
35
36 There are three flavors of SFrame FRE representation in the binary format:
37 - sframe_frame_row_entry_addr1 where the FRE start address is 1 byte.
38 - sframe_frame_row_entry_addr2 where the FRE start address is 2 bytes.
39 - sframe_frame_row_entry_addr4 where the FRE start address is 4 bytes.
40
41 Note that in the SFrame format, all SFrame FREs of a function use one
42 single representation. The SFrame FRE type itself is identified via the
43 information in the SFrame FDE function info.
44
45 Now, to select the minimum required one from the list above, one needs to
46 make a decision based on the size (in bytes) of the function.
47
48 As a result, for this optimization, some fragments (generated with a new
49 type rs_sframe) for the SFrame section are fixed up later.
50
51 This optimization (for size) is enabled by default. */
52
53 #ifndef SFRAME_FRE_TYPE_SELECTION_OPT
54 # define SFRAME_FRE_TYPE_SELECTION_OPT 1
55 #endif
56
57 /* List of SFrame FDE entries. */
58
59 static struct sframe_func_entry *all_sframe_fdes = NULL;
60
61 /* Tail of the list to add to. */
62
63 static struct sframe_func_entry **last_sframe_fde = &all_sframe_fdes;
64
65 /* Emit a single byte into the current segment. */
66
67 static inline void
68 out_one (int byte)
69 {
70 FRAG_APPEND_1_CHAR (byte);
71 }
72
73 /* Emit a two-byte word into the current segment. */
74
75 static inline void
76 out_two (int data)
77 {
78 md_number_to_chars (frag_more (2), data, 2);
79 }
80
81 /* Emit a four byte word into the current segment. */
82
83 static inline void
84 out_four (int data)
85 {
86 md_number_to_chars (frag_more (4), data, 4);
87 }
88
89 /* Get the start address symbol from the DWARF FDE. */
90
91 static symbolS*
92 get_dw_fde_start_addrS (const struct fde_entry *dw_fde)
93 {
94 return dw_fde->start_address;
95 }
96
97 /* Get the start address symbol from the DWARF FDE. */
98
99 static symbolS*
100 get_dw_fde_end_addrS (const struct fde_entry *dw_fde)
101 {
102 return dw_fde->end_address;
103 }
104
105 /* Get whether PAUTH B key is used. */
106 static bool
107 get_dw_fde_pauth_b_key_p (const struct fde_entry *dw_fde ATTRIBUTE_UNUSED)
108 {
109 #ifdef tc_fde_entry_extras
110 return (dw_fde->pauth_key == AARCH64_PAUTH_KEY_B);
111 #else
112 return false;
113 #endif
114 }
115
116 /* SFrame Frame Row Entry (FRE) related functions. */
117
118 static void
119 sframe_fre_set_begin_addr (struct sframe_row_entry *fre, symbolS *beginS)
120 {
121 fre->pc_begin = beginS;
122 }
123
124 static void
125 sframe_fre_set_end_addr (struct sframe_row_entry *fre, symbolS *endS)
126 {
127 fre->pc_end = endS;
128 }
129
130 static void
131 sframe_fre_set_cfa_base_reg (struct sframe_row_entry *fre,
132 unsigned int cfa_base_reg)
133 {
134 fre->cfa_base_reg = cfa_base_reg;
135 fre->merge_candidate = false;
136 }
137
138 static offsetT
139 sframe_fre_get_cfa_offset (const struct sframe_row_entry * fre)
140 {
141 offsetT offset = fre->cfa_offset;
142
143 /* For s390x undo adjustment of CFA offset (to enable 8-bit offsets). */
144 if (sframe_get_abi_arch () == SFRAME_ABI_S390X_ENDIAN_BIG)
145 offset = SFRAME_V2_S390X_CFA_OFFSET_DECODE (offset);
146
147 return offset;
148 }
149
150 static void
151 sframe_fre_set_cfa_offset (struct sframe_row_entry *fre,
152 offsetT cfa_offset)
153 {
154 /* For s390x adjust CFA offset to enable 8-bit offsets. */
155 if (sframe_get_abi_arch () == SFRAME_ABI_S390X_ENDIAN_BIG)
156 cfa_offset = SFRAME_V2_S390X_CFA_OFFSET_ENCODE (cfa_offset);
157
158 fre->cfa_offset = cfa_offset;
159 fre->merge_candidate = false;
160 }
161
162 static void
163 sframe_fre_set_ra_track (struct sframe_row_entry *fre, offsetT ra_offset)
164 {
165 fre->ra_loc = SFRAME_FRE_ELEM_LOC_STACK;
166 fre->ra_offset = ra_offset;
167 fre->merge_candidate = false;
168 }
169
170 static void
171 sframe_fre_set_bp_track (struct sframe_row_entry *fre, offsetT bp_offset)
172 {
173 fre->bp_loc = SFRAME_FRE_ELEM_LOC_STACK;
174 fre->bp_offset = bp_offset;
175 fre->merge_candidate = false;
176 }
177
178 /* All stack offset values within an FRE are uniformly encoded in the same
179 number of bytes. The size of the stack offset values will, however, vary
180 across FREs. */
181
182 #define VALUE_8BIT 0x7f
183 #define VALUE_16BIT 0x7fff
184 #define VALUE_32BIT 0x7fffffff
185 #define VALUE_64BIT 0x7fffffffffffffff
186
187 /* Given a signed offset, return the size in bytes needed to represent it. */
188
189 static unsigned int
190 get_offset_size_in_bytes (offsetT value)
191 {
192 unsigned int size = 0;
193
194 if (value <= VALUE_8BIT && value >= (offsetT) -VALUE_8BIT)
195 size = 1;
196 else if (value <= VALUE_16BIT && value >= (offsetT) -VALUE_16BIT)
197 size = 2;
198 else if (value <= VALUE_32BIT && value >= (offsetT) -VALUE_32BIT)
199 size = 4;
200 else if ((sizeof (offsetT) > 4) && (value <= (offsetT) VALUE_64BIT
201 && value >= (offsetT) -VALUE_64BIT))
202 size = 8;
203
204 return size;
205 }
206
207 #define SFRAME_FRE_OFFSET_FUNC_MAP_INDEX_1B 0 /* SFRAME_FRE_OFFSET_1B. */
208 #define SFRAME_FRE_OFFSET_FUNC_MAP_INDEX_2B 1 /* SFRAME_FRE_OFFSET_2B. */
209 #define SFRAME_FRE_OFFSET_FUNC_MAP_INDEX_4B 2 /* SFRAME_FRE_OFFSET_4B. */
210 #define SFRAME_FRE_OFFSET_FUNC_MAP_INDEX_8B 3 /* Not supported in SFrame. */
211 #define SFRAME_FRE_OFFSET_FUNC_MAP_INDEX_MAX SFRAME_FRE_OFFSET_FUNC_MAP_INDEX_8B
212
213 /* Helper struct for mapping offset size to output functions. */
214
215 struct sframe_fre_offset_func_map
216 {
217 unsigned int offset_size;
218 void (*out_func)(int);
219 };
220
221 /* Given an OFFSET_SIZE, return the size in bytes needed to represent it. */
222
223 static unsigned int
224 sframe_fre_offset_func_map_index (unsigned int offset_size)
225 {
226 unsigned int idx = SFRAME_FRE_OFFSET_FUNC_MAP_INDEX_MAX;
227
228 switch (offset_size)
229 {
230 case SFRAME_FRE_OFFSET_1B:
231 idx = SFRAME_FRE_OFFSET_FUNC_MAP_INDEX_1B;
232 break;
233 case SFRAME_FRE_OFFSET_2B:
234 idx = SFRAME_FRE_OFFSET_FUNC_MAP_INDEX_2B;
235 break;
236 case SFRAME_FRE_OFFSET_4B:
237 idx = SFRAME_FRE_OFFSET_FUNC_MAP_INDEX_4B;
238 break;
239 default:
240 /* Not supported in SFrame. */
241 break;
242 }
243
244 return idx;
245 }
246
247 /* Mapping from offset size to the output function to emit the value. */
248
249 static const
250 struct sframe_fre_offset_func_map
251 fre_offset_func_map[SFRAME_FRE_OFFSET_FUNC_MAP_INDEX_MAX+1] =
252 {
253 { SFRAME_FRE_OFFSET_1B, out_one },
254 { SFRAME_FRE_OFFSET_2B, out_two },
255 { SFRAME_FRE_OFFSET_4B, out_four },
256 { -1, NULL } /* Not Supported in SFrame. */
257 };
258
259 /* SFrame version specific operations access. */
260
261 static struct sframe_version_ops sframe_ver_ops;
262
263 /* SFrame (SFRAME_VERSION_1) set FRE info. */
264
265 static unsigned char
266 sframe_v1_set_fre_info (unsigned int base_reg, unsigned int num_offsets,
267 unsigned int offset_size, bool mangled_ra_p)
268 {
269 unsigned char fre_info;
270 fre_info = SFRAME_V1_FRE_INFO (base_reg, num_offsets, offset_size);
271 fre_info = SFRAME_V1_FRE_INFO_UPDATE_MANGLED_RA_P (mangled_ra_p, fre_info);
272 return fre_info;
273 }
274
275 /* SFrame (SFRAME_VERSION_1) set function info. */
276 static unsigned char
277 sframe_v1_set_func_info (unsigned int fde_type, unsigned int fre_type,
278 unsigned int pauth_key)
279 {
280 unsigned char func_info;
281 func_info = SFRAME_V1_FUNC_INFO (fde_type, fre_type);
282 func_info = SFRAME_V1_FUNC_INFO_UPDATE_PAUTH_KEY (pauth_key, func_info);
283 return func_info;
284 }
285
286 /* SFrame version specific operations setup. */
287
288 static void
289 sframe_set_version (uint32_t sframe_version ATTRIBUTE_UNUSED)
290 {
291 sframe_ver_ops.format_version = SFRAME_VERSION_2;
292
293 /* These operations remain the same for SFRAME_VERSION_2 as fre_info and
294 func_info have not changed from SFRAME_VERSION_1. */
295
296 sframe_ver_ops.set_fre_info = sframe_v1_set_fre_info;
297
298 sframe_ver_ops.set_func_info = sframe_v1_set_func_info;
299 }
300
301 /* SFrame set FRE info. */
302
303 static unsigned char
304 sframe_set_fre_info (unsigned int base_reg, unsigned int num_offsets,
305 unsigned int offset_size, bool mangled_ra_p)
306 {
307 return sframe_ver_ops.set_fre_info (base_reg, num_offsets,
308 offset_size, mangled_ra_p);
309 }
310
311 /* SFrame set func info. */
312
313 static unsigned char
314 sframe_set_func_info (unsigned int fde_type, unsigned int fre_type,
315 unsigned int pauth_key)
316 {
317 return sframe_ver_ops.set_func_info (fde_type, fre_type, pauth_key);
318 }
319
320 /* Get the number of SFrame FDEs for the current file. */
321
322 static unsigned int
323 get_num_sframe_fdes (void);
324
325 /* Get the number of SFrame frame row entries for the current file. */
326
327 static unsigned int
328 get_num_sframe_fres (void);
329
330 /* Get CFA base register ID as represented in SFrame Frame Row Entry. */
331
332 static unsigned int
333 get_fre_base_reg_id (struct sframe_row_entry *sframe_fre)
334 {
335 unsigned int cfi_insn_cfa_base_reg = sframe_fre->cfa_base_reg;
336 unsigned fre_base_reg = SFRAME_BASE_REG_SP;
337
338 if (cfi_insn_cfa_base_reg == SFRAME_CFA_FP_REG)
339 fre_base_reg = SFRAME_BASE_REG_FP;
340
341 /* Only one bit is reserved in SFRAME_VERSION_1. */
342 gas_assert (fre_base_reg == SFRAME_BASE_REG_SP
343 || fre_base_reg == SFRAME_BASE_REG_FP);
344
345 return fre_base_reg;
346 }
347
348 /* Get number of offsets necessary for the SFrame Frame Row Entry. */
349
350 static unsigned int
351 get_fre_num_offsets (struct sframe_row_entry *sframe_fre)
352 {
353 /* Atleast 1 must always be present (to recover CFA). */
354 unsigned int fre_num_offsets = 1;
355
356 if (sframe_fre->bp_loc == SFRAME_FRE_ELEM_LOC_STACK)
357 fre_num_offsets++;
358 if (sframe_ra_tracking_p ()
359 && (sframe_fre->ra_loc == SFRAME_FRE_ELEM_LOC_STACK
360 /* For s390x account padding RA offset, if FP without RA saved. */
361 || (sframe_get_abi_arch () == SFRAME_ABI_S390X_ENDIAN_BIG
362 && sframe_fre->bp_loc == SFRAME_FRE_ELEM_LOC_STACK)))
363 fre_num_offsets++;
364 return fre_num_offsets;
365 }
366
367 /* Get the minimum necessary offset size (in bytes) for this
368 SFrame frame row entry. */
369
370 static unsigned int
371 sframe_get_fre_offset_size (struct sframe_row_entry *sframe_fre)
372 {
373 unsigned int max_offset_size = 0;
374 unsigned int cfa_offset_size = 0;
375 unsigned int bp_offset_size = 0;
376 unsigned int ra_offset_size = 0;
377
378 unsigned int fre_offset_size = 0;
379
380 /* What size of offsets appear in this frame row entry. */
381 cfa_offset_size = get_offset_size_in_bytes (sframe_fre->cfa_offset);
382 if (sframe_fre->bp_loc == SFRAME_FRE_ELEM_LOC_STACK)
383 bp_offset_size = get_offset_size_in_bytes (sframe_fre->bp_offset);
384 if (sframe_ra_tracking_p ())
385 {
386 if (sframe_fre->ra_loc == SFRAME_FRE_ELEM_LOC_STACK)
387 ra_offset_size = get_offset_size_in_bytes (sframe_fre->ra_offset);
388 /* For s390x account padding RA offset, if FP without RA saved. */
389 else if (sframe_get_abi_arch () == SFRAME_ABI_S390X_ENDIAN_BIG
390 && sframe_fre->bp_loc == SFRAME_FRE_ELEM_LOC_STACK)
391 ra_offset_size = get_offset_size_in_bytes (SFRAME_FRE_RA_OFFSET_INVALID);
392 }
393
394 /* Get the maximum size needed to represent the offsets. */
395 max_offset_size = cfa_offset_size;
396 if (bp_offset_size > max_offset_size)
397 max_offset_size = bp_offset_size;
398 if (ra_offset_size > max_offset_size)
399 max_offset_size = ra_offset_size;
400
401 gas_assert (max_offset_size);
402
403 switch (max_offset_size)
404 {
405 case 1:
406 fre_offset_size = SFRAME_FRE_OFFSET_1B;
407 break;
408 case 2:
409 fre_offset_size = SFRAME_FRE_OFFSET_2B;
410 break;
411 case 4:
412 fre_offset_size = SFRAME_FRE_OFFSET_4B;
413 break;
414 default:
415 /* Offset of size 8 bytes is not supported in SFrame format
416 version 1. */
417 as_fatal (_("SFrame unsupported offset value\n"));
418 break;
419 }
420
421 return fre_offset_size;
422 }
423
424 #if SFRAME_FRE_TYPE_SELECTION_OPT
425
426 /* Create a composite expression CEXP (for SFrame FRE start address) such that:
427
428 exp = <val> OP_absent <width>, where,
429
430 - <val> and <width> are themselves expressionS.
431 - <val> stores the expression which when evaluated gives the value of the
432 start address offset of the FRE.
433 - <width> stores the expression when evaluated gives the number of bytes
434 needed to encode the start address offset of the FRE.
435
436 The use of OP_absent as the X_op_symbol helps identify this expression
437 later when fragments are fixed up. */
438
439 static void
440 create_fre_start_addr_exp (expressionS *cexp, symbolS *fre_pc_begin,
441 symbolS *fde_start_address,
442 symbolS *fde_end_address)
443 {
444 expressionS val;
445 expressionS width;
446
447 /* val expression stores the FDE start address offset from the start PC
448 of function. */
449 val.X_op = O_subtract;
450 val.X_add_symbol = fre_pc_begin;
451 val.X_op_symbol = fde_start_address;
452 val.X_add_number = 0;
453
454 /* width expressions stores the size of the function. This is used later
455 to determine the number of bytes to be used to encode the FRE start
456 address of each FRE of the function. */
457 width.X_op = O_subtract;
458 width.X_add_symbol = fde_end_address;
459 width.X_op_symbol = fde_start_address;
460 width.X_add_number = 0;
461
462 cexp->X_op = O_absent;
463 cexp->X_add_symbol = make_expr_symbol (&val);
464 cexp->X_op_symbol = make_expr_symbol (&width);
465 cexp->X_add_number = 0;
466 }
467
468 /* Create a composite expression CEXP (for SFrame FDE function info) such that:
469
470 exp = <rest_of_func_info> OP_modulus <width>, where,
471
472 - <rest_of_func_info> and <width> are themselves expressionS.
473 - <rest_of_func_info> stores a constant expression where X_add_number is
474 used to stash away the func_info. The upper 4-bits of the func_info are copied
475 back to the resulting byte by the fragment fixup logic.
476 - <width> stores the expression when evaluated gives the size of the
477 function in number of bytes.
478
479 The use of OP_modulus as the X_op_symbol helps identify this expression
480 later when fragments are fixed up. */
481
482 static void
483 create_func_info_exp (expressionS *cexp, symbolS *dw_fde_end_addrS,
484 symbolS *dw_fde_start_addrS, uint8_t func_info)
485 {
486 expressionS width;
487 expressionS rest_of_func_info;
488
489 width.X_op = O_subtract;
490 width.X_add_symbol = dw_fde_end_addrS;
491 width.X_op_symbol = dw_fde_start_addrS;
492 width.X_add_number = 0;
493
494 rest_of_func_info.X_op = O_constant;
495 rest_of_func_info.X_add_number = func_info;
496
497 cexp->X_op = O_modulus;
498 cexp->X_add_symbol = make_expr_symbol (&rest_of_func_info);
499 cexp->X_op_symbol = make_expr_symbol (&width);
500 cexp->X_add_number = 0;
501 }
502
503 #endif
504
505 static struct sframe_row_entry*
506 sframe_row_entry_new (void)
507 {
508 struct sframe_row_entry *fre = XCNEW (struct sframe_row_entry);
509 /* Reset cfa_base_reg to -1. A value of 0 will imply some valid register
510 for the supported arches. */
511 fre->cfa_base_reg = SFRAME_FRE_BASE_REG_INVAL;
512 fre->merge_candidate = true;
513 /* Reset the mangled RA status bit to zero by default. We will
514 initialize it in sframe_row_entry_initialize () with the sticky
515 bit if set. */
516 fre->mangled_ra_p = false;
517
518 return fre;
519 }
520
521 static void
522 sframe_row_entry_free (struct sframe_row_entry *fre)
523 {
524 while (fre)
525 {
526 struct sframe_row_entry *fre_next = fre->next;
527 XDELETE (fre);
528 fre = fre_next;
529 }
530 }
531
532 /* Allocate an SFrame FDE. */
533
534 static struct sframe_func_entry*
535 sframe_fde_alloc (void)
536 {
537 return XCNEW (struct sframe_func_entry);
538 }
539
540 /* Free up the SFrame FDE. */
541
542 static void
543 sframe_fde_free (struct sframe_func_entry *sframe_fde)
544 {
545 sframe_row_entry_free (sframe_fde->sframe_fres);
546 XDELETE (sframe_fde);
547 }
548
549 static void
550 output_sframe_row_entry (symbolS *fde_start_addr,
551 symbolS *fde_end_addr,
552 struct sframe_row_entry *sframe_fre)
553 {
554 unsigned char fre_info;
555 unsigned int fre_num_offsets;
556 unsigned int fre_offset_size;
557 unsigned int fre_base_reg;
558 expressionS exp;
559 unsigned int fre_addr_size;
560
561 unsigned int idx = 0;
562 unsigned int fre_write_offsets = 0;
563
564 fre_addr_size = 4; /* 4 bytes by default. FIXME tie it to fre_type? */
565
566 /* SFrame FRE Start Address. */
567 #if SFRAME_FRE_TYPE_SELECTION_OPT
568 create_fre_start_addr_exp (&exp, sframe_fre->pc_begin, fde_start_addr,
569 fde_end_addr);
570 frag_grow (fre_addr_size);
571 frag_var (rs_sframe, fre_addr_size, 0, 0,
572 make_expr_symbol (&exp), 0, (char *) frag_now);
573 #else
574 gas_assert (fde_end_addr);
575 exp.X_op = O_subtract;
576 exp.X_add_symbol = sframe_fre->pc_begin; /* to. */
577 exp.X_op_symbol = fde_start_addr; /* from. */
578 exp.X_add_number = 0;
579 emit_expr (&exp, fre_addr_size);
580 #endif
581
582 /* Create the fre_info using the CFA base register, number of offsets and max
583 size of offset in this frame row entry. */
584 fre_base_reg = get_fre_base_reg_id (sframe_fre);
585 fre_num_offsets = get_fre_num_offsets (sframe_fre);
586 fre_offset_size = sframe_get_fre_offset_size (sframe_fre);
587 fre_info = sframe_set_fre_info (fre_base_reg, fre_num_offsets,
588 fre_offset_size, sframe_fre->mangled_ra_p);
589 out_one (fre_info);
590
591 idx = sframe_fre_offset_func_map_index (fre_offset_size);
592 gas_assert (idx < SFRAME_FRE_OFFSET_FUNC_MAP_INDEX_MAX);
593
594 /* Write out the offsets in order - cfa, bp, ra. */
595 fre_offset_func_map[idx].out_func (sframe_fre->cfa_offset);
596 fre_write_offsets++;
597
598 if (sframe_ra_tracking_p ())
599 {
600 if (sframe_fre->ra_loc == SFRAME_FRE_ELEM_LOC_STACK)
601 {
602 fre_offset_func_map[idx].out_func (sframe_fre->ra_offset);
603 fre_write_offsets++;
604 }
605 /* For s390x write padding RA offset, if FP without RA saved. */
606 else if (sframe_get_abi_arch () == SFRAME_ABI_S390X_ENDIAN_BIG
607 && sframe_fre->bp_loc == SFRAME_FRE_ELEM_LOC_STACK)
608 {
609 fre_offset_func_map[idx].out_func (SFRAME_FRE_RA_OFFSET_INVALID);
610 fre_write_offsets++;
611 }
612 }
613 if (sframe_fre->bp_loc == SFRAME_FRE_ELEM_LOC_STACK)
614 {
615 fre_offset_func_map[idx].out_func (sframe_fre->bp_offset);
616 fre_write_offsets++;
617 }
618
619 /* Check if the expected number offsets have been written out
620 in this FRE. */
621 gas_assert (fre_write_offsets == fre_num_offsets);
622 }
623
624 static void
625 output_sframe_funcdesc (symbolS *start_of_fre_section,
626 symbolS *fre_symbol,
627 struct sframe_func_entry *sframe_fde)
628 {
629 expressionS exp;
630 symbolS *dw_fde_start_addrS, *dw_fde_end_addrS;
631 unsigned int pauth_key;
632
633 dw_fde_start_addrS = get_dw_fde_start_addrS (sframe_fde->dw_fde);
634 dw_fde_end_addrS = get_dw_fde_end_addrS (sframe_fde->dw_fde);
635
636 /* Start address of the function. gas always emits this value with encoding
637 SFRAME_F_FDE_FUNC_START_PCREL. See PR ld/32666. */
638 exp.X_op = O_subtract;
639 exp.X_add_symbol = dw_fde_start_addrS; /* to location. */
640 exp.X_op_symbol = symbol_temp_new_now (); /* from location. */
641 exp.X_add_number = 0;
642 emit_expr (&exp, sizeof_member (sframe_func_desc_entry,
643 sfde_func_start_address));
644
645 /* Size of the function in bytes. */
646 exp.X_op = O_subtract;
647 exp.X_add_symbol = dw_fde_end_addrS;
648 exp.X_op_symbol = dw_fde_start_addrS;
649 exp.X_add_number = 0;
650 emit_expr (&exp, sizeof_member (sframe_func_desc_entry,
651 sfde_func_size));
652
653 /* Offset to the first frame row entry. */
654 exp.X_op = O_subtract;
655 exp.X_add_symbol = fre_symbol; /* Minuend. */
656 exp.X_op_symbol = start_of_fre_section; /* Subtrahend. */
657 exp.X_add_number = 0;
658 emit_expr (&exp, sizeof_member (sframe_func_desc_entry,
659 sfde_func_start_fre_off));
660
661 /* Number of FREs. */
662 out_four (sframe_fde->num_fres);
663
664 /* SFrame FDE function info. */
665 unsigned char func_info;
666 pauth_key = (get_dw_fde_pauth_b_key_p (sframe_fde->dw_fde)
667 ? SFRAME_AARCH64_PAUTH_KEY_B : SFRAME_AARCH64_PAUTH_KEY_A);
668 func_info = sframe_set_func_info (SFRAME_FDE_TYPE_PCINC,
669 SFRAME_FRE_TYPE_ADDR4,
670 pauth_key);
671 #if SFRAME_FRE_TYPE_SELECTION_OPT
672 expressionS cexp;
673 create_func_info_exp (&cexp, dw_fde_end_addrS, dw_fde_start_addrS,
674 func_info);
675 frag_grow (1); /* Size of func info is unsigned char. */
676 frag_var (rs_sframe, 1, 0, 0, make_expr_symbol (&cexp), 0,
677 (char *) frag_now);
678 #else
679 out_one (func_info);
680 #endif
681 out_one (0);
682 out_two (0);
683 }
684
685 static void
686 output_sframe_internal (void)
687 {
688 expressionS exp;
689 unsigned int i = 0;
690
691 symbolS *end_of_frame_hdr;
692 symbolS *end_of_frame_section;
693 symbolS *start_of_func_desc_section;
694 symbolS *start_of_fre_section;
695 struct sframe_func_entry *sframe_fde, *sframe_fde_next;
696 struct sframe_row_entry *sframe_fre;
697 unsigned char abi_arch = 0;
698 int fixed_fp_offset = SFRAME_CFA_FIXED_FP_INVALID;
699 int fixed_ra_offset = SFRAME_CFA_FIXED_RA_INVALID;
700
701 /* The function descriptor entries as dumped by the assembler are not
702 sorted on PCs. Fix for PR ld/32666 requires setting of an additional
703 flag in SFrame Version 2. */
704 unsigned char sframe_flags = SFRAME_F_FDE_FUNC_START_PCREL;
705
706 unsigned int num_fdes = get_num_sframe_fdes ();
707 unsigned int num_fres = get_num_sframe_fres ();
708 symbolS **fde_fre_symbols = XNEWVEC (symbolS *, num_fdes);
709 for (i = 0; i < num_fdes; i++)
710 fde_fre_symbols[i] = symbol_temp_make ();
711
712 end_of_frame_hdr = symbol_temp_make ();
713 start_of_fre_section = symbol_temp_make ();
714 start_of_func_desc_section = symbol_temp_make ();
715 end_of_frame_section = symbol_temp_make ();
716
717 /* Output the preamble of SFrame section. */
718 out_two (SFRAME_MAGIC);
719 out_one (SFRAME_VERSION);
720 /* gas must ensure emitted SFrame sections have at least the required flags
721 set. */
722 gas_assert ((sframe_flags & SFRAME_V2_GNU_AS_LD_ENCODING_FLAGS)
723 == SFRAME_V2_GNU_AS_LD_ENCODING_FLAGS);
724 out_one (sframe_flags);
725 /* abi/arch. */
726 #ifdef sframe_get_abi_arch
727 abi_arch = sframe_get_abi_arch ();
728 #endif
729 gas_assert (abi_arch);
730 out_one (abi_arch);
731
732 /* Offset for the FP register from CFA. Neither of the AMD64 or AAPCS64
733 ABIs have a fixed offset for the FP register from the CFA. This may be
734 useful in future (but not without additional support in the toolchain)
735 for specialized handling/encoding for cases where, for example,
736 -fno-omit-frame-pointer is used. */
737 out_one (fixed_fp_offset);
738
739 /* All ABIs participating in SFrame generation must define
740 sframe_ra_tracking_p.
741 When RA tracking (in FREs) is not needed (e.g., AMD64), SFrame assumes
742 the RA is going to be at a fixed offset from CFA. Check that the fixed RA
743 offset is appropriately defined in all cases. */
744 if (!sframe_ra_tracking_p ())
745 {
746 fixed_ra_offset = sframe_cfa_ra_offset ();
747 gas_assert (fixed_ra_offset != SFRAME_CFA_FIXED_RA_INVALID);
748 }
749 out_one (fixed_ra_offset);
750
751 /* None of the AMD64, AARCH64, or s390x ABIs need the auxiliary header.
752 When the need does arise to use this field, the appropriate backend
753 must provide this information. */
754 out_one (0); /* Auxiliary SFrame header length. */
755
756 out_four (num_fdes); /* Number of FDEs. */
757 out_four (num_fres); /* Number of FREs. */
758
759 /* Size of FRE sub-section. */
760 exp.X_op = O_subtract;
761 exp.X_add_symbol = end_of_frame_section;
762 exp.X_op_symbol = start_of_fre_section;
763 exp.X_add_number = 0;
764 emit_expr (&exp, sizeof_member (sframe_header, sfh_fre_len));
765
766 /* Offset of FDE sub-section. */
767 exp.X_op = O_subtract;
768 exp.X_add_symbol = end_of_frame_hdr;
769 exp.X_op_symbol = start_of_func_desc_section;
770 exp.X_add_number = 0;
771 emit_expr (&exp, sizeof_member (sframe_header, sfh_fdeoff));
772
773 /* Offset of FRE sub-section. */
774 exp.X_op = O_subtract;
775 exp.X_add_symbol = start_of_fre_section;
776 exp.X_op_symbol = end_of_frame_hdr;
777 exp.X_add_number = 0;
778 emit_expr (&exp, sizeof_member (sframe_header, sfh_freoff));
779
780 symbol_set_value_now (end_of_frame_hdr);
781 symbol_set_value_now (start_of_func_desc_section);
782
783 /* Output the SFrame function descriptor entries. */
784 i = 0;
785 for (sframe_fde = all_sframe_fdes; sframe_fde; sframe_fde = sframe_fde->next)
786 {
787 output_sframe_funcdesc (start_of_fre_section,
788 fde_fre_symbols[i], sframe_fde);
789 i++;
790 }
791
792 symbol_set_value_now (start_of_fre_section);
793
794 /* Output the SFrame FREs. */
795 i = 0;
796 sframe_fde = all_sframe_fdes;
797
798 for (sframe_fde = all_sframe_fdes; sframe_fde; sframe_fde = sframe_fde_next)
799 {
800 symbol_set_value_now (fde_fre_symbols[i]);
801 for (sframe_fre = sframe_fde->sframe_fres;
802 sframe_fre;
803 sframe_fre = sframe_fre->next)
804 {
805 output_sframe_row_entry (get_dw_fde_start_addrS (sframe_fde->dw_fde),
806 get_dw_fde_end_addrS (sframe_fde->dw_fde),
807 sframe_fre);
808 }
809 i++;
810 sframe_fde_next = sframe_fde->next;
811 sframe_fde_free (sframe_fde);
812 }
813 all_sframe_fdes = NULL;
814 last_sframe_fde = &all_sframe_fdes;
815
816 symbol_set_value_now (end_of_frame_section);
817
818 gas_assert (i == num_fdes);
819
820 free (fde_fre_symbols);
821 fde_fre_symbols = NULL;
822 }
823
824 static unsigned int
825 get_num_sframe_fdes (void)
826 {
827 struct sframe_func_entry *sframe_fde;
828 unsigned int total_fdes = 0;
829
830 for (sframe_fde = all_sframe_fdes; sframe_fde ; sframe_fde = sframe_fde->next)
831 total_fdes++;
832
833 return total_fdes;
834 }
835
836 /* Get the total number of SFrame row entries across the FDEs. */
837
838 static unsigned int
839 get_num_sframe_fres (void)
840 {
841 struct sframe_func_entry *sframe_fde;
842 unsigned int total_fres = 0;
843
844 for (sframe_fde = all_sframe_fdes; sframe_fde ; sframe_fde = sframe_fde->next)
845 total_fres += sframe_fde->num_fres;
846
847 return total_fres;
848 }
849
850 /* SFrame translation context functions. */
851
852 /* Allocate a new SFrame translation context. */
853
854 static struct sframe_xlate_ctx*
855 sframe_xlate_ctx_alloc (void)
856 {
857 struct sframe_xlate_ctx* xlate_ctx = XCNEW (struct sframe_xlate_ctx);
858 return xlate_ctx;
859 }
860
861 /* Initialize the given SFrame translation context. */
862
863 static void
864 sframe_xlate_ctx_init (struct sframe_xlate_ctx *xlate_ctx)
865 {
866 xlate_ctx->dw_fde = NULL;
867 xlate_ctx->first_fre = NULL;
868 xlate_ctx->last_fre = NULL;
869 xlate_ctx->cur_fre = NULL;
870 xlate_ctx->remember_fre = NULL;
871 xlate_ctx->num_xlate_fres = 0;
872 }
873
874 /* Cleanup the given SFrame translation context. */
875
876 static void
877 sframe_xlate_ctx_cleanup (struct sframe_xlate_ctx *xlate_ctx)
878 {
879 sframe_row_entry_free (xlate_ctx->first_fre);
880 XDELETE (xlate_ctx->remember_fre);
881 XDELETE (xlate_ctx->cur_fre);
882 }
883
884 /* Transfer the state from the SFrame translation context to the SFrame FDE. */
885
886 static void
887 sframe_xlate_ctx_finalize (struct sframe_xlate_ctx *xlate_ctx,
888 struct sframe_func_entry *sframe_fde)
889 {
890 sframe_fde->dw_fde = xlate_ctx->dw_fde;
891 sframe_fde->sframe_fres = xlate_ctx->first_fre;
892 sframe_fde->num_fres = xlate_ctx->num_xlate_fres;
893 }
894
895 /* Add the given FRE in the list of frame row entries in the given FDE
896 translation context. */
897
898 static void
899 sframe_xlate_ctx_add_fre (struct sframe_xlate_ctx *xlate_ctx,
900 struct sframe_row_entry *fre)
901 {
902 gas_assert (xlate_ctx && fre);
903
904 /* Add the frame row entry. */
905 if (!xlate_ctx->first_fre)
906 xlate_ctx->first_fre = fre;
907 else if (xlate_ctx->last_fre)
908 xlate_ctx->last_fre->next = fre;
909
910 xlate_ctx->last_fre = fre;
911
912 /* Keep track of the total number of SFrame frame row entries. */
913 xlate_ctx->num_xlate_fres++;
914 }
915
916 /* A SFrame Frame Row Entry is self-sufficient in terms of stack tracing info
917 for a given PC. It contains information assimilated from multiple CFI
918 instructions, and hence, a new SFrame FRE is initialized with the data from
919 the previous known FRE, if any.
920
921 Understandably, not all information (especially the instruction begin
922 and end boundaries) needs to be relayed. Hence, the caller of this API
923 must set the pc_begin and pc_end as applicable. */
924
925 static void
926 sframe_row_entry_initialize (struct sframe_row_entry *cur_fre,
927 struct sframe_row_entry *prev_fre)
928 {
929 gas_assert (prev_fre);
930 cur_fre->cfa_base_reg = prev_fre->cfa_base_reg;
931 cur_fre->cfa_offset = prev_fre->cfa_offset;
932 cur_fre->bp_loc = prev_fre->bp_loc;
933 cur_fre->bp_offset = prev_fre->bp_offset;
934 cur_fre->ra_loc = prev_fre->ra_loc;
935 cur_fre->ra_offset = prev_fre->ra_offset;
936 /* Treat RA mangling as a sticky bit. It retains its value until another
937 .cfi_negate_ra_state is seen. */
938 cur_fre->mangled_ra_p = prev_fre->mangled_ra_p;
939 }
940
941 /* Return SFrame register name for SP, FP, and RA, or NULL if other. */
942
943 static const char *
944 sframe_register_name (unsigned int reg)
945 {
946 if (reg == SFRAME_CFA_SP_REG)
947 return "SP";
948 else if (reg == SFRAME_CFA_FP_REG)
949 return "FP";
950 else if (reg == SFRAME_CFA_RA_REG)
951 return "RA";
952 else
953 return NULL;
954 }
955
956 /* Translate DW_CFA_advance_loc into SFrame context.
957 Return SFRAME_XLATE_OK if success. */
958
959 static int
960 sframe_xlate_do_advance_loc (struct sframe_xlate_ctx *xlate_ctx,
961 struct cfi_insn_data *cfi_insn)
962 {
963 struct sframe_row_entry *last_fre = xlate_ctx->last_fre;
964 /* Get the scratchpad FRE currently being updated as the cfi_insn's
965 get interpreted. This FRE eventually gets linked in into the
966 list of FREs for the specific function. */
967 struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
968
969 if (cur_fre)
970 {
971 if (!cur_fre->merge_candidate)
972 {
973 sframe_fre_set_end_addr (cur_fre, cfi_insn->u.ll.lab2);
974
975 sframe_xlate_ctx_add_fre (xlate_ctx, cur_fre);
976 last_fre = xlate_ctx->last_fre;
977
978 xlate_ctx->cur_fre = sframe_row_entry_new ();
979 cur_fre = xlate_ctx->cur_fre;
980
981 if (last_fre)
982 sframe_row_entry_initialize (cur_fre, last_fre);
983 }
984 else
985 {
986 sframe_fre_set_end_addr (last_fre, cfi_insn->u.ll.lab2);
987 gas_assert (last_fre->merge_candidate == false);
988 }
989 }
990 else
991 {
992 xlate_ctx->cur_fre = sframe_row_entry_new ();
993 cur_fre = xlate_ctx->cur_fre;
994 }
995
996 gas_assert (cur_fre);
997 sframe_fre_set_begin_addr (cur_fre, cfi_insn->u.ll.lab2);
998
999 return SFRAME_XLATE_OK;
1000 }
1001
1002 /* Translate DW_CFA_def_cfa into SFrame context.
1003 Return SFRAME_XLATE_OK if success. */
1004
1005 static int
1006 sframe_xlate_do_def_cfa (struct sframe_xlate_ctx *xlate_ctx,
1007 struct cfi_insn_data *cfi_insn)
1008
1009 {
1010 /* Get the scratchpad FRE. This FRE will eventually get linked in. */
1011 struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
1012 if (!cur_fre)
1013 {
1014 xlate_ctx->cur_fre = sframe_row_entry_new ();
1015 cur_fre = xlate_ctx->cur_fre;
1016 sframe_fre_set_begin_addr (cur_fre,
1017 get_dw_fde_start_addrS (xlate_ctx->dw_fde));
1018 }
1019 /* Define the current CFA rule to use the provided register and
1020 offset. However, if the register is not FP/SP, skip creating
1021 SFrame stack trace info for the function. */
1022 if (cfi_insn->u.ri.reg != SFRAME_CFA_SP_REG
1023 && cfi_insn->u.ri.reg != SFRAME_CFA_FP_REG)
1024 {
1025 as_warn (_("no SFrame FDE emitted; "
1026 "non-SP/FP register %u in .cfi_def_cfa"),
1027 cfi_insn->u.ri.reg);
1028 return SFRAME_XLATE_ERR_NOTREPRESENTED; /* Not represented. */
1029 }
1030 sframe_fre_set_cfa_base_reg (cur_fre, cfi_insn->u.ri.reg);
1031 sframe_fre_set_cfa_offset (cur_fre, cfi_insn->u.ri.offset);
1032 cur_fre->merge_candidate = false;
1033
1034 return SFRAME_XLATE_OK;
1035 }
1036
1037 /* Translate DW_CFA_def_cfa_register into SFrame context.
1038 Return SFRAME_XLATE_OK if success. */
1039
1040 static int
1041 sframe_xlate_do_def_cfa_register (struct sframe_xlate_ctx *xlate_ctx,
1042 struct cfi_insn_data *cfi_insn)
1043 {
1044 struct sframe_row_entry *last_fre = xlate_ctx->last_fre;
1045 /* Get the scratchpad FRE. This FRE will eventually get linked in. */
1046 struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
1047
1048 gas_assert (cur_fre);
1049 /* Define the current CFA rule to use the provided register (but to
1050 keep the old offset). However, if the register is not FP/SP,
1051 skip creating SFrame stack trace info for the function. */
1052 if (cfi_insn->u.r != SFRAME_CFA_SP_REG
1053 && cfi_insn->u.r != SFRAME_CFA_FP_REG)
1054 {
1055 as_warn (_("no SFrame FDE emitted; "
1056 "non-SP/FP register %u in .cfi_def_cfa_register"),
1057 cfi_insn->u.r);
1058 return SFRAME_XLATE_ERR_NOTREPRESENTED; /* Not represented. */
1059 }
1060 sframe_fre_set_cfa_base_reg (cur_fre, cfi_insn->u.r);
1061 if (last_fre)
1062 sframe_fre_set_cfa_offset (cur_fre, sframe_fre_get_cfa_offset (last_fre));
1063
1064 cur_fre->merge_candidate = false;
1065
1066 return SFRAME_XLATE_OK;
1067 }
1068
1069 /* Translate DW_CFA_def_cfa_offset into SFrame context.
1070 Return SFRAME_XLATE_OK if success. */
1071
1072 static int
1073 sframe_xlate_do_def_cfa_offset (struct sframe_xlate_ctx *xlate_ctx,
1074 struct cfi_insn_data *cfi_insn)
1075 {
1076 /* The scratchpad FRE currently being updated with each cfi_insn
1077 being interpreted. This FRE eventually gets linked in into the
1078 list of FREs for the specific function. */
1079 struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
1080
1081 gas_assert (cur_fre);
1082 /* Define the current CFA rule to use the provided offset (but to keep
1083 the old register). However, if the old register is not FP/SP,
1084 skip creating SFrame stack trace info for the function. */
1085 if ((cur_fre->cfa_base_reg == SFRAME_CFA_FP_REG)
1086 || (cur_fre->cfa_base_reg == SFRAME_CFA_SP_REG))
1087 {
1088 sframe_fre_set_cfa_offset (cur_fre, cfi_insn->u.i);
1089 cur_fre->merge_candidate = false;
1090 }
1091 else
1092 {
1093 /* No CFA base register in effect. Non-SP/FP CFA base register should
1094 not occur, as sframe_xlate_do_def_cfa[_register] would detect this. */
1095 as_warn (_("no SFrame FDE emitted; "
1096 ".cfi_def_cfa_offset without CFA base register in effect"));
1097 return SFRAME_XLATE_ERR_NOTREPRESENTED;
1098 }
1099
1100 return SFRAME_XLATE_OK;
1101 }
1102
1103 /* Translate DW_CFA_offset into SFrame context.
1104 Return SFRAME_XLATE_OK if success. */
1105
1106 static int
1107 sframe_xlate_do_offset (struct sframe_xlate_ctx *xlate_ctx,
1108 struct cfi_insn_data *cfi_insn)
1109 {
1110 /* The scratchpad FRE currently being updated with each cfi_insn
1111 being interpreted. This FRE eventually gets linked in into the
1112 list of FREs for the specific function. */
1113 struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
1114
1115 gas_assert (cur_fre);
1116 /* Change the rule for the register indicated by the register number to
1117 be the specified offset. */
1118 /* Ignore SP reg, as it can be recovered from the CFA tracking info. */
1119 if (cfi_insn->u.ri.reg == SFRAME_CFA_FP_REG)
1120 {
1121 gas_assert (!cur_fre->base_reg);
1122 sframe_fre_set_bp_track (cur_fre, cfi_insn->u.ri.offset);
1123 cur_fre->merge_candidate = false;
1124 }
1125 else if (sframe_ra_tracking_p ()
1126 && cfi_insn->u.ri.reg == SFRAME_CFA_RA_REG)
1127 {
1128 sframe_fre_set_ra_track (cur_fre, cfi_insn->u.ri.offset);
1129 cur_fre->merge_candidate = false;
1130 }
1131 /* This is used to track changes to non-rsp registers, skip all others
1132 except FP / RA for now. */
1133 return SFRAME_XLATE_OK;
1134 }
1135
1136 /* Translate DW_CFA_val_offset into SFrame context.
1137 Return SFRAME_XLATE_OK if success.
1138
1139 When CFI_ESC_P is true, the CFI_INSN is hand-crafted using CFI_escape
1140 data. See sframe_xlate_do_escape_val_offset. */
1141
1142 static int
1143 sframe_xlate_do_val_offset (const struct sframe_xlate_ctx *xlate_ctx ATTRIBUTE_UNUSED,
1144 const struct cfi_insn_data *cfi_insn,
1145 bool cfi_esc_p)
1146 {
1147 /* Previous value of register is CFA + offset. However, if the specified
1148 register is not interesting (SP, FP, or RA reg), the current
1149 DW_CFA_val_offset instruction can be safely skipped without sacrificing
1150 the asynchronicity of stack trace information. */
1151 if (cfi_insn->u.ri.reg == SFRAME_CFA_FP_REG
1152 || (sframe_ra_tracking_p () && cfi_insn->u.ri.reg == SFRAME_CFA_RA_REG)
1153 /* Ignore SP reg, if offset matches assumed default rule. */
1154 || (cfi_insn->u.ri.reg == SFRAME_CFA_SP_REG
1155 && ((sframe_get_abi_arch () != SFRAME_ABI_S390X_ENDIAN_BIG
1156 && cfi_insn->u.ri.offset != 0)
1157 || (sframe_get_abi_arch () == SFRAME_ABI_S390X_ENDIAN_BIG
1158 && cfi_insn->u.ri.offset != SFRAME_S390X_SP_VAL_OFFSET))))
1159 {
1160 as_warn (_("no SFrame FDE emitted; %s with %s reg %u"),
1161 cfi_esc_p ? ".cfi_escape DW_CFA_val_offset" : ".cfi_val_offset",
1162 sframe_register_name (cfi_insn->u.ri.reg), cfi_insn->u.ri.reg);
1163 return SFRAME_XLATE_ERR_NOTREPRESENTED; /* Not represented. */
1164 }
1165
1166 /* Safe to skip. */
1167 return SFRAME_XLATE_OK;
1168 }
1169
1170 /* S390-specific translate DW_CFA_register into SFrame context.
1171 Return SFRAME_XLATE_OK if success. */
1172
1173 static int
1174 s390_sframe_xlate_do_register (struct sframe_xlate_ctx *xlate_ctx,
1175 struct cfi_insn_data *cfi_insn)
1176 {
1177 /* The scratchpad FRE currently being updated with each cfi_insn
1178 being interpreted. This FRE eventually gets linked in into the
1179 list of FREs for the specific function. */
1180 struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
1181
1182 gas_assert (cur_fre);
1183
1184 /* Change the rule for the register indicated by the register number to
1185 be the specified register. Encode the register number as offset by
1186 shifting it to the left by one and setting the least-significant bit
1187 (LSB). The LSB can be used to differentiate offsets from register
1188 numbers, as offsets from CFA are always a multiple of -8 on s390x. */
1189 if (cfi_insn->u.rr.reg1 == SFRAME_CFA_FP_REG)
1190 sframe_fre_set_bp_track (cur_fre,
1191 SFRAME_V2_S390X_OFFSET_ENCODE_REGNUM (cfi_insn->u.rr.reg2));
1192 else if (sframe_ra_tracking_p ()
1193 && cfi_insn->u.rr.reg1 == SFRAME_CFA_RA_REG)
1194 sframe_fre_set_ra_track (cur_fre,
1195 SFRAME_V2_S390X_OFFSET_ENCODE_REGNUM (cfi_insn->u.rr.reg2));
1196
1197 return SFRAME_XLATE_OK;
1198 }
1199
1200 /* Translate DW_CFA_register into SFrame context.
1201 Return SFRAME_XLATE_OK if success. */
1202
1203 static int
1204 sframe_xlate_do_register (struct sframe_xlate_ctx *xlate_ctx ATTRIBUTE_UNUSED,
1205 struct cfi_insn_data *cfi_insn)
1206 {
1207 /* Conditionally invoke S390-specific implementation. */
1208 if (sframe_get_abi_arch () == SFRAME_ABI_S390X_ENDIAN_BIG)
1209 return s390_sframe_xlate_do_register (xlate_ctx, cfi_insn);
1210
1211 /* Previous value of register1 is register2. However, if the specified
1212 register1 is not interesting (FP or RA reg), the current DW_CFA_register
1213 instruction can be safely skipped without sacrificing the asynchronicity of
1214 stack trace information. */
1215 if (cfi_insn->u.rr.reg1 == SFRAME_CFA_FP_REG
1216 || (sframe_ra_tracking_p () && cfi_insn->u.rr.reg1 == SFRAME_CFA_RA_REG)
1217 /* Ignore SP reg, as it can be recovered from the CFA tracking info. */
1218 )
1219 {
1220 as_warn (_("no SFrame FDE emitted; %s register %u in .cfi_register"),
1221 sframe_register_name (cfi_insn->u.rr.reg1), cfi_insn->u.rr.reg1);
1222 return SFRAME_XLATE_ERR_NOTREPRESENTED; /* Not represented. */
1223 }
1224
1225 /* Safe to skip. */
1226 return SFRAME_XLATE_OK;
1227 }
1228
1229 /* Translate DW_CFA_remember_state into SFrame context.
1230 Return SFRAME_XLATE_OK if success. */
1231
1232 static int
1233 sframe_xlate_do_remember_state (struct sframe_xlate_ctx *xlate_ctx)
1234 {
1235 struct sframe_row_entry *last_fre = xlate_ctx->last_fre;
1236
1237 /* If there is no FRE state to remember, nothing to do here. Return
1238 early with non-zero error code, this will cause no SFrame stack trace
1239 info for the function involved. */
1240 if (!last_fre)
1241 {
1242 as_warn (_("no SFrame FDE emitted; "
1243 ".cfi_remember_state without prior SFrame FRE state"));
1244 return SFRAME_XLATE_ERR_INVAL;
1245 }
1246
1247 if (!xlate_ctx->remember_fre)
1248 xlate_ctx->remember_fre = sframe_row_entry_new ();
1249 sframe_row_entry_initialize (xlate_ctx->remember_fre, last_fre);
1250
1251 return SFRAME_XLATE_OK;
1252 }
1253
1254 /* Translate DW_CFA_restore_state into SFrame context.
1255 Return SFRAME_XLATE_OK if success. */
1256
1257 static int
1258 sframe_xlate_do_restore_state (struct sframe_xlate_ctx *xlate_ctx)
1259 {
1260 /* The scratchpad FRE currently being updated with each cfi_insn
1261 being interpreted. This FRE eventually gets linked in into the
1262 list of FREs for the specific function. */
1263 struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
1264
1265 gas_assert (xlate_ctx->remember_fre);
1266 gas_assert (cur_fre && cur_fre->merge_candidate);
1267
1268 /* Get the CFA state from the DW_CFA_remember_state insn. */
1269 sframe_row_entry_initialize (cur_fre, xlate_ctx->remember_fre);
1270 /* The PC boundaries of the current SFrame FRE are updated
1271 via other machinery. */
1272 cur_fre->merge_candidate = false;
1273 return SFRAME_XLATE_OK;
1274 }
1275
1276 /* Translate DW_CFA_restore into SFrame context.
1277 Return SFRAME_XLATE_OK if success. */
1278
1279 static int
1280 sframe_xlate_do_restore (struct sframe_xlate_ctx *xlate_ctx,
1281 struct cfi_insn_data *cfi_insn)
1282 {
1283 struct sframe_row_entry *cie_fre = xlate_ctx->first_fre;
1284 /* The scratchpad FRE currently being updated with each cfi_insn
1285 being interpreted. This FRE eventually gets linked in into the
1286 list of FREs for the specific function. */
1287 struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
1288
1289 /* PR gas/33170. It is valid to have a:
1290 .cfi_restore N
1291 even at the entry of a function; in which case cie_fre is not yet setup.
1292 Point cie_fre to cur_fre, and let the machinery proceed to update
1293 merge_candidate as usual. */
1294 if (cie_fre == NULL)
1295 cie_fre = cur_fre;
1296
1297 /* Change the rule for the indicated register to the rule assigned to
1298 it by the initial_instructions in the CIE. SFrame FREs track only CFA
1299 and FP / RA for backtracing purposes; skip the other .cfi_restore
1300 directives. */
1301 if (cfi_insn->u.r == SFRAME_CFA_FP_REG)
1302 {
1303 gas_assert (cur_fre);
1304 cur_fre->bp_loc = cie_fre->bp_loc;
1305 cur_fre->bp_offset = cie_fre->bp_offset;
1306 cur_fre->merge_candidate = false;
1307 }
1308 else if (sframe_ra_tracking_p ()
1309 && cfi_insn->u.r == SFRAME_CFA_RA_REG)
1310 {
1311 gas_assert (cur_fre);
1312 cur_fre->ra_loc = cie_fre->ra_loc;
1313 cur_fre->ra_offset = cie_fre->ra_offset;
1314 cur_fre->merge_candidate = false;
1315 }
1316 return SFRAME_XLATE_OK;
1317 }
1318
1319 /* Translate DW_CFA_AARCH64_negate_ra_state into SFrame context.
1320 Return SFRAME_XLATE_OK if success. */
1321
1322 static int
1323 sframe_xlate_do_aarch64_negate_ra_state (struct sframe_xlate_ctx *xlate_ctx,
1324 struct cfi_insn_data *cfi_insn ATTRIBUTE_UNUSED)
1325 {
1326 struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
1327
1328 gas_assert (cur_fre);
1329 /* Toggle the mangled RA status bit. */
1330 cur_fre->mangled_ra_p = !cur_fre->mangled_ra_p;
1331 cur_fre->merge_candidate = false;
1332
1333 return SFRAME_XLATE_OK;
1334 }
1335
1336 /* Translate DW_CFA_AARCH64_negate_ra_state_with_pc into SFrame context.
1337 Return SFRAME_XLATE_OK if success. */
1338
1339 static int
1340 sframe_xlate_do_aarch64_negate_ra_state_with_pc (struct sframe_xlate_ctx *xlate_ctx ATTRIBUTE_UNUSED,
1341 struct cfi_insn_data *cfi_insn ATTRIBUTE_UNUSED)
1342 {
1343 as_warn (_("no SFrame FDE emitted; .cfi_negate_ra_state_with_pc"));
1344 /* The used signing method should be encoded inside the FDE in SFrame v3.
1345 For now, PAuth_LR extension is not supported with SFrame. */
1346 return SFRAME_XLATE_ERR_NOTREPRESENTED; /* Not represented. */
1347 }
1348
1349 /* Translate DW_CFA_GNU_window_save into SFrame context.
1350 DW_CFA_GNU_window_save is a DWARF Sparc extension, but is multiplexed with a
1351 directive of DWARF AArch64 extension: DW_CFA_AARCH64_negate_ra_state.
1352 The AArch64 backend of GCC 14 and older versions was emitting mistakenly the
1353 Sparc CFI directive (.cfi_window_save). From GCC 15, the AArch64 backend
1354 only emits .cfi_negate_ra_state. For backward compatibility, the handler for
1355 .cfi_window_save needs to check whether the directive was used in a AArch64
1356 ABI context or not.
1357 Return SFRAME_XLATE_OK if success. */
1358
1359 static int
1360 sframe_xlate_do_gnu_window_save (struct sframe_xlate_ctx *xlate_ctx,
1361 struct cfi_insn_data *cfi_insn)
1362 {
1363 unsigned char abi_arch = sframe_get_abi_arch ();
1364
1365 /* Translate DW_CFA_AARCH64_negate_ra_state into SFrame context. */
1366 if (abi_arch == SFRAME_ABI_AARCH64_ENDIAN_BIG
1367 || abi_arch == SFRAME_ABI_AARCH64_ENDIAN_LITTLE)
1368 return sframe_xlate_do_aarch64_negate_ra_state (xlate_ctx, cfi_insn);
1369
1370 as_warn (_("no SFrame FDE emitted; .cfi_window_save"));
1371 return SFRAME_XLATE_ERR_NOTREPRESENTED; /* Not represented. */
1372 }
1373
1374 /* Handle DW_CFA_expression in .cfi_escape.
1375
1376 As with sframe_xlate_do_cfi_escape, the intent of this function is to detect
1377 only the simple-to-process but common cases, where skipping over the escape
1378 expr data does not affect correctness of the SFrame stack trace data.
1379
1380 Sets CALLER_WARN_P for skipped cases (and returns SFRAME_XLATE_OK) where the
1381 caller must warn. The caller then must also set
1382 SFRAME_XLATE_ERR_NOTREPRESENTED for their callers. */
1383
1384 static int
1385 sframe_xlate_do_escape_expr (const struct sframe_xlate_ctx *xlate_ctx,
1386 const struct cfi_insn_data *cfi_insn,
1387 bool *caller_warn_p)
1388 {
1389 const struct cfi_escape_data *e = cfi_insn->u.esc;
1390 int err = SFRAME_XLATE_OK;
1391 unsigned int reg = 0;
1392 unsigned int i = 0;
1393
1394 /* Check roughly for an expression
1395 DW_CFA_expression: r1 (rdx) (DW_OP_bregN (reg): OFFSET). */
1396 #define CFI_ESC_NUM_EXP 4
1397 offsetT items[CFI_ESC_NUM_EXP] = {0};
1398 while (e->next)
1399 {
1400 e = e->next;
1401 if ((i == 2 && (items[1] != 2)) /* Expected len of 2 in DWARF expr. */
1402 /* We do not care for the exact values of items[2] and items[3],
1403 so an explicit check for O_constant isnt necessary either. */
1404 || i >= CFI_ESC_NUM_EXP
1405 || (i < 2
1406 && (e->exp.X_op != O_constant
1407 || e->type != CFI_ESC_byte
1408 || e->reloc != TC_PARSE_CONS_RETURN_NONE)))
1409 goto warn_and_exit;
1410 items[i] = e->exp.X_add_number;
1411 i++;
1412 }
1413
1414 if (i <= CFI_ESC_NUM_EXP - 1)
1415 goto warn_and_exit;
1416
1417 /* reg operand to DW_CFA_expression is ULEB128. For the purpose at hand,
1418 however, the register value will be less than 128 (CFI_ESC_NUM_EXP set
1419 to 4). See an extended comment in sframe_xlate_do_escape_expr for why
1420 reading ULEB is okay to skip without sacrificing correctness. */
1421 reg = items[0];
1422 #undef CFI_ESC_NUM_EXP
1423
1424 if (reg == SFRAME_CFA_SP_REG || reg == SFRAME_CFA_FP_REG
1425 || (sframe_ra_tracking_p () && reg == SFRAME_CFA_RA_REG)
1426 || reg == xlate_ctx->cur_fre->cfa_base_reg)
1427 {
1428 as_warn (_("no SFrame FDE emitted; "
1429 ".cfi_escape DW_CFA_expression with %s reg %u"),
1430 sframe_register_name (reg), reg);
1431 err = SFRAME_XLATE_ERR_NOTREPRESENTED;
1432 }
1433 /* else safe to skip, so continue to return SFRAME_XLATE_OK. */
1434
1435 return err;
1436
1437 warn_and_exit:
1438 *caller_warn_p = true;
1439 return err;
1440 }
1441
1442 /* Handle DW_CFA_val_offset in .cfi_escape.
1443
1444 As with sframe_xlate_do_cfi_escape, the intent of this function is to detect
1445 only the simple-to-process but common cases, where skipping over the escape
1446 expr data does not affect correctness of the SFrame stack trace data.
1447
1448 Sets CALLER_WARN_P for skipped cases (and returns SFRAME_XLATE_OK) where the
1449 caller must warn. The caller then must also set
1450 SFRAME_XLATE_ERR_NOTREPRESENTED for their callers. */
1451
1452 static int
1453 sframe_xlate_do_escape_val_offset (const struct sframe_xlate_ctx *xlate_ctx,
1454 const struct cfi_insn_data *cfi_insn,
1455 bool *caller_warn_p)
1456 {
1457 const struct cfi_escape_data *e = cfi_insn->u.esc;
1458 int err = SFRAME_XLATE_OK;
1459 unsigned int i = 0;
1460 unsigned int reg;
1461 offsetT offset;
1462
1463 /* Check for (DW_CFA_val_offset reg scaled_offset) sequence. */
1464 #define CFI_ESC_NUM_EXP 2
1465 offsetT items[CFI_ESC_NUM_EXP] = {0};
1466 while (e->next)
1467 {
1468 e = e->next;
1469 if (i >= CFI_ESC_NUM_EXP || e->exp.X_op != O_constant
1470 || e->type != CFI_ESC_byte
1471 || e->reloc != TC_PARSE_CONS_RETURN_NONE)
1472 goto warn_and_exit;
1473 items[i] = e->exp.X_add_number;
1474 i++;
1475 }
1476 if (i <= CFI_ESC_NUM_EXP - 1)
1477 goto warn_and_exit;
1478
1479 /* Both arguments to DW_CFA_val_offset are ULEB128. Especially with APX (on
1480 x86) we're going to see DWARF register numbers above 127, for the extended
1481 GPRs. And large enough stack frames would also require multi-byte offset
1482 representation. However, since we limit our focus on cases when
1483 CFI_ESC_NUM_EXP is 2, reading ULEB can be skipped. IOW, although not
1484 ideal, SFrame FDE generation in case of an APX register in
1485 DW_CFA_val_offset is being skipped (PS: this does _not_ mean incorrect
1486 SFrame stack trace data).
1487
1488 Recall that the intent here is to check for simple and prevalent cases,
1489 when feasible. */
1490
1491 reg = items[0];
1492 offset = items[1];
1493 #undef CFI_ESC_NUM_EXP
1494
1495 /* Invoke sframe_xlate_do_val_offset itself for checking. */
1496 struct cfi_insn_data temp = {
1497 .insn = DW_CFA_val_offset,
1498 .u = {
1499 .ri = {
1500 .reg = reg,
1501 .offset = offset * DWARF2_CIE_DATA_ALIGNMENT
1502 }
1503 }
1504 };
1505 err = sframe_xlate_do_val_offset (xlate_ctx, &temp, true);
1506 return err;
1507
1508 warn_and_exit:
1509 *caller_warn_p = true;
1510 return err;
1511 }
1512
1513 /* Handle CFI_escape in SFrame context.
1514
1515 .cfi_escape CFI directive allows the user to add arbitrary data to the
1516 unwind info. DWARF expressions commonly follow after CFI_escape (fake CFI)
1517 DWARF opcode. One might also use CFI_escape to add OS-specific CFI opcodes
1518 even.
1519
1520 Complex unwind info added using .cfi_escape directive _may_ be of no
1521 consequence for SFrame when the affected registers are not SP, FP, RA or
1522 CFA. The challenge in confirming the afore-mentioned is that it needs full
1523 parsing (and validation) of the data presented after .cfi_escape. Here we
1524 take a case-by-case approach towards skipping _some_ instances of
1525 .cfi_escape: skip those that can be *easily* determined to be harmless in
1526 the context of SFrame stack trace information.
1527
1528 This function partially processes data following .cfi_escape and returns
1529 SFRAME_XLATE_OK if OK to skip. */
1530
1531 static int
1532 sframe_xlate_do_cfi_escape (const struct sframe_xlate_ctx *xlate_ctx,
1533 const struct cfi_insn_data *cfi_insn)
1534 {
1535 const struct cfi_escape_data *e;
1536 bool warn_p = false;
1537 int err = SFRAME_XLATE_OK;
1538 offsetT firstop;
1539
1540 e = cfi_insn->u.esc;
1541
1542 if (!e)
1543 return SFRAME_XLATE_ERR_INVAL;
1544
1545 if (e->exp.X_op != O_constant
1546 || e->type != CFI_ESC_byte
1547 || e->reloc != TC_PARSE_CONS_RETURN_NONE)
1548 return SFRAME_XLATE_ERR_NOTREPRESENTED;
1549
1550 firstop = e->exp.X_add_number;
1551 switch (firstop)
1552 {
1553 case DW_CFA_nop:
1554 /* One or more nops together are harmless for SFrame. */
1555 while (e->next)
1556 {
1557 e = e->next;
1558 if (e->exp.X_op != O_constant || e->exp.X_add_number != DW_CFA_nop
1559 || e->type != CFI_ESC_byte
1560 || e->reloc != TC_PARSE_CONS_RETURN_NONE)
1561 {
1562 warn_p = true;
1563 break;
1564 }
1565 }
1566 break;
1567
1568 case DW_CFA_expression:
1569 err = sframe_xlate_do_escape_expr (xlate_ctx, cfi_insn, &warn_p);
1570 break;
1571
1572 case DW_CFA_val_offset:
1573 err = sframe_xlate_do_escape_val_offset (xlate_ctx, cfi_insn, &warn_p);
1574 break;
1575
1576 /* FIXME - Also add processing for DW_CFA_GNU_args_size in future? */
1577
1578 default:
1579 warn_p = true;
1580 break;
1581 }
1582
1583 if (warn_p)
1584 {
1585 /* In all other cases (e.g., DW_CFA_def_cfa_expression or other
1586 OS-specific CFI opcodes), skip inspecting the DWARF expression.
1587 This may impact the asynchronicity due to loss of coverage.
1588 Continue to warn the user and bail out. */
1589 as_warn (_("no SFrame FDE emitted; .cfi_escape with op (%#lx)"),
1590 (unsigned long)firstop);
1591 err = SFRAME_XLATE_ERR_NOTREPRESENTED;
1592 }
1593
1594 return err;
1595 }
1596
1597 /* Translate DW_CFA_undefined into SFrame context.
1598
1599 DW_CFA_undefined op indicates that from now on, the previous value of
1600 register cant be restored anymore. In SFrame stack trace, we cannot
1601 represent such a semantic. So, we skip generating an SFrame FDE for this,
1602 when a register of interest is used with DW_CFA_undefined.
1603
1604 Return SFRAME_XLATE_OK if success. */
1605
1606 static int
1607 sframe_xlate_do_cfi_undefined (const struct sframe_xlate_ctx *xlate_ctx ATTRIBUTE_UNUSED,
1608 const struct cfi_insn_data *cfi_insn)
1609 {
1610 if (cfi_insn->u.r == SFRAME_CFA_FP_REG
1611 || cfi_insn->u.r == SFRAME_CFA_RA_REG
1612 || cfi_insn->u.r == SFRAME_CFA_SP_REG)
1613 {
1614 as_warn (_("no SFrame FDE emitted; %s reg %u in .cfi_undefined"),
1615 sframe_register_name (cfi_insn->u.r), cfi_insn->u.r);
1616 return SFRAME_XLATE_ERR_NOTREPRESENTED; /* Not represented. */
1617 }
1618
1619 /* Safe to skip. */
1620 return SFRAME_XLATE_OK;
1621 }
1622
1623 /* Translate DW_CFA_same_value into SFrame context.
1624
1625 DW_CFA_same_value op indicates that current value of register is the same as
1626 in the previous frame, i.e. no restoration needed. In SFrame stack trace
1627 format, the handling is done similar to DW_CFA_restore.
1628
1629 For SFRAME_CFA_RA_REG, if RA-tracking is enabled, reset the SFrame FRE state
1630 for REG_RA to indicate that register does not need restoration. P.S.: Even
1631 though resetting just REG_RA may be contradicting the AArch64 ABI (as Frame
1632 Record contains for FP and LR), sframe_xlate_do_same_value () does not
1633 detect the case and assumes the users' DW_CFA_same_value SFRAME_CFA_RA_REG
1634 has a sound reason. For ABIs, where RA-tracking is disabled, handle it
1635 similar to DW_CFA_restore: ignore the directive, it is safe to skip. The
1636 reasoning is similar to that for DW_CFA_restore: if such a restoration was
1637 meant to be of any consequence, there must have been the necessary CFI
1638 directives for updating the CFA rule too such that the recovered RA from
1639 stack is valid.
1640
1641 SFrame based stacktracers will implement CFA-based SP recovery for all ABIs:
1642 SP for previous frame is based on the applicable CFA-rule. There is no
1643 representation in SFrame to indicate "no restoration needed" for REG_SP,
1644 when going to the previous frame. That said, if DW_CFA_same_value is seen
1645 for SFRAME_CFA_SP_REG, handle it similar to DW_CFA_restore: ignore the
1646 directive, it is safe to skip. The reasoning is similar to that for
1647 DW_CFA_restore: if such a restoration was meant to be of any consequence,
1648 there must have been the necessary CFI directives for updating the CFA rule
1649 too. The latter will be duly processed by the SFrame generation code, as
1650 expected.
1651
1652 For SFRAME_CFA_FP_REG, reset the state of the current FRE to indicate that
1653 the value is the same as previous frame.
1654
1655 Return SFRAME_XLATE_OK if success. */
1656
1657 static int
1658 sframe_xlate_do_same_value (const struct sframe_xlate_ctx *xlate_ctx,
1659 const struct cfi_insn_data *cfi_insn)
1660 {
1661 struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
1662
1663 if (sframe_ra_tracking_p () && cfi_insn->u.r == SFRAME_CFA_RA_REG)
1664 {
1665 cur_fre->ra_loc = SFRAME_FRE_ELEM_LOC_REG;
1666 cur_fre->ra_offset = 0;
1667 cur_fre->merge_candidate = false;
1668 }
1669 else if (cfi_insn->u.r == SFRAME_CFA_FP_REG)
1670 {
1671 cur_fre->bp_loc = SFRAME_FRE_ELEM_LOC_REG;
1672 cur_fre->bp_offset = 0;
1673 cur_fre->merge_candidate = false;
1674 }
1675
1676 /* Safe to skip. */
1677 return SFRAME_XLATE_OK;
1678 }
1679
1680 /* Returns the DWARF call frame instruction name or fake CFI name for the
1681 specified CFI opcode, or NULL if the value is not recognized. */
1682
1683 static const char *
1684 sframe_get_cfi_name (int cfi_opc)
1685 {
1686 const char *cfi_name;
1687
1688 switch (cfi_opc)
1689 {
1690 /* Fake CFI type; outside the byte range of any real CFI insn. */
1691 /* See gas/dw2gencfi.h. */
1692 case CFI_adjust_cfa_offset:
1693 cfi_name = "CFI_adjust_cfa_offset";
1694 break;
1695 case CFI_return_column:
1696 cfi_name = "CFI_return_column";
1697 break;
1698 case CFI_rel_offset:
1699 cfi_name = "CFI_rel_offset";
1700 break;
1701 case CFI_escape:
1702 cfi_name = "CFI_escape";
1703 break;
1704 case CFI_signal_frame:
1705 cfi_name = "CFI_signal_frame";
1706 break;
1707 case CFI_val_encoded_addr:
1708 cfi_name = "CFI_val_encoded_addr";
1709 break;
1710 case CFI_label:
1711 cfi_name = "CFI_label";
1712 break;
1713 default:
1714 cfi_name = get_DW_CFA_name (cfi_opc);
1715 }
1716
1717 return cfi_name;
1718 }
1719
1720 /* Process CFI_INSN and update the translation context with the FRE
1721 information.
1722
1723 Returns an error code (sframe_xlate_err) if CFI_INSN is not successfully
1724 processed. */
1725
1726 static int
1727 sframe_do_cfi_insn (struct sframe_xlate_ctx *xlate_ctx,
1728 struct cfi_insn_data *cfi_insn)
1729 {
1730 int err = 0;
1731
1732 /* Atleast one cfi_insn per FDE is expected. */
1733 gas_assert (cfi_insn);
1734 int op = cfi_insn->insn;
1735
1736 switch (op)
1737 {
1738 case DW_CFA_advance_loc:
1739 err = sframe_xlate_do_advance_loc (xlate_ctx, cfi_insn);
1740 break;
1741 case DW_CFA_def_cfa:
1742 err = sframe_xlate_do_def_cfa (xlate_ctx, cfi_insn);
1743 break;
1744 case DW_CFA_def_cfa_register:
1745 err = sframe_xlate_do_def_cfa_register (xlate_ctx, cfi_insn);
1746 break;
1747 case DW_CFA_def_cfa_offset:
1748 err = sframe_xlate_do_def_cfa_offset (xlate_ctx, cfi_insn);
1749 break;
1750 case DW_CFA_offset:
1751 err = sframe_xlate_do_offset (xlate_ctx, cfi_insn);
1752 break;
1753 case DW_CFA_val_offset:
1754 err = sframe_xlate_do_val_offset (xlate_ctx, cfi_insn, false);
1755 break;
1756 case DW_CFA_remember_state:
1757 err = sframe_xlate_do_remember_state (xlate_ctx);
1758 break;
1759 case DW_CFA_restore_state:
1760 err = sframe_xlate_do_restore_state (xlate_ctx);
1761 break;
1762 case DW_CFA_restore:
1763 err = sframe_xlate_do_restore (xlate_ctx, cfi_insn);
1764 break;
1765 /* DW_CFA_AARCH64_negate_ra_state is multiplexed with
1766 DW_CFA_GNU_window_save. */
1767 case DW_CFA_GNU_window_save:
1768 err = sframe_xlate_do_gnu_window_save (xlate_ctx, cfi_insn);
1769 break;
1770 case DW_CFA_AARCH64_negate_ra_state_with_pc:
1771 err = sframe_xlate_do_aarch64_negate_ra_state_with_pc (xlate_ctx, cfi_insn);
1772 break;
1773 case DW_CFA_register:
1774 err = sframe_xlate_do_register (xlate_ctx, cfi_insn);
1775 break;
1776 case CFI_escape:
1777 err = sframe_xlate_do_cfi_escape (xlate_ctx, cfi_insn);
1778 break;
1779 case DW_CFA_undefined:
1780 err = sframe_xlate_do_cfi_undefined (xlate_ctx, cfi_insn);
1781 break;
1782 case DW_CFA_same_value:
1783 err = sframe_xlate_do_same_value (xlate_ctx, cfi_insn);
1784 break;
1785 default:
1786 /* Other skipped operations may, however, impact the asynchronicity. */
1787 {
1788 const char *cfi_name = sframe_get_cfi_name (op);
1789
1790 if (!cfi_name)
1791 cfi_name = _("(unknown)");
1792 as_warn (_("no SFrame FDE emitted; CFI insn %s (%#x)"),
1793 cfi_name, op);
1794 err = SFRAME_XLATE_ERR_NOTREPRESENTED;
1795 }
1796 }
1797
1798 /* Any error will cause no SFrame FDE later. The user has already been
1799 warned. */
1800 return err;
1801 }
1802
1803
1804 static int
1805 sframe_do_fde (struct sframe_xlate_ctx *xlate_ctx,
1806 const struct fde_entry *dw_fde)
1807 {
1808 struct cfi_insn_data *cfi_insn;
1809 int err = SFRAME_XLATE_OK;
1810
1811 xlate_ctx->dw_fde = dw_fde;
1812
1813 /* SFrame format cannot represent a non-default DWARF return column reg. */
1814 if (xlate_ctx->dw_fde->return_column != DWARF2_DEFAULT_RETURN_COLUMN)
1815 {
1816 as_warn (_("no SFrame FDE emitted; non-default RA register %u"),
1817 xlate_ctx->dw_fde->return_column);
1818 return SFRAME_XLATE_ERR_NOTREPRESENTED;
1819 }
1820
1821 /* Iterate over the CFIs and create SFrame FREs. */
1822 for (cfi_insn = dw_fde->data; cfi_insn; cfi_insn = cfi_insn->next)
1823 {
1824 /* Translate each CFI, and buffer the state in translation context. */
1825 err = sframe_do_cfi_insn (xlate_ctx, cfi_insn);
1826 if (err != SFRAME_XLATE_OK)
1827 {
1828 /* Skip generating SFrame stack trace info for the function if any
1829 offending CFI is encountered by sframe_do_cfi_insn (). Warning
1830 message already printed by sframe_do_cfi_insn (). */
1831 return err; /* Return the error code. */
1832 }
1833 }
1834
1835 /* Link in the scratchpad FRE that the last few CFI insns helped create. */
1836 if (xlate_ctx->cur_fre)
1837 {
1838 sframe_xlate_ctx_add_fre (xlate_ctx, xlate_ctx->cur_fre);
1839 xlate_ctx->cur_fre = NULL;
1840 }
1841 /* Designate the end of the last SFrame FRE. */
1842 if (xlate_ctx->last_fre)
1843 {
1844 xlate_ctx->last_fre->pc_end
1845 = get_dw_fde_end_addrS (xlate_ctx->dw_fde);
1846 }
1847
1848 /* ABI/arch except s390x cannot represent FP without RA saved. */
1849 if (sframe_ra_tracking_p ()
1850 && sframe_get_abi_arch () != SFRAME_ABI_S390X_ENDIAN_BIG)
1851 {
1852 struct sframe_row_entry *fre;
1853
1854 /* Iterate over the scratchpad FREs and validate them. */
1855 for (fre = xlate_ctx->first_fre; fre; fre = fre->next)
1856 {
1857 /* SFrame format cannot represent FP on stack without RA on stack. */
1858 if (fre->ra_loc != SFRAME_FRE_ELEM_LOC_STACK
1859 && fre->bp_loc == SFRAME_FRE_ELEM_LOC_STACK)
1860 {
1861 as_warn (_("no SFrame FDE emitted; FP without RA on stack"));
1862 return SFRAME_XLATE_ERR_NOTREPRESENTED;
1863 }
1864 }
1865 }
1866
1867 return SFRAME_XLATE_OK;
1868 }
1869
1870 /* Create SFrame stack trace info for all functions.
1871
1872 This function consumes the already generated DWARF FDEs (by dw2gencfi) and
1873 generates data which is later emitted as stack trace information encoded in
1874 the SFrame format. */
1875
1876 static void
1877 create_sframe_all (void)
1878 {
1879 struct fde_entry *dw_fde = NULL;
1880 struct sframe_func_entry *sframe_fde = NULL;
1881
1882 struct sframe_xlate_ctx *xlate_ctx = sframe_xlate_ctx_alloc ();
1883
1884 for (dw_fde = all_fde_data; dw_fde ; dw_fde = dw_fde->next)
1885 {
1886 sframe_fde = sframe_fde_alloc ();
1887 /* Initialize the translation context with information anew. */
1888 sframe_xlate_ctx_init (xlate_ctx);
1889
1890 /* Process and link SFrame FDEs if no error. Also skip adding an SFrame
1891 FDE if it does not contain any SFrame FREs. There is little use of an
1892 SFrame FDE if there is no stack tracing information for the
1893 function. */
1894 int err = sframe_do_fde (xlate_ctx, dw_fde);
1895 if (err || xlate_ctx->num_xlate_fres == 0)
1896 {
1897 sframe_xlate_ctx_cleanup (xlate_ctx);
1898 sframe_fde_free (sframe_fde);
1899 }
1900 else
1901 {
1902 /* All done. Transfer the state from the SFrame translation
1903 context to the SFrame FDE. */
1904 sframe_xlate_ctx_finalize (xlate_ctx, sframe_fde);
1905 *last_sframe_fde = sframe_fde;
1906 last_sframe_fde = &sframe_fde->next;
1907 }
1908 }
1909
1910 XDELETE (xlate_ctx);
1911 }
1912
1913 void
1914 output_sframe (segT sframe_seg)
1915 {
1916 (void) sframe_seg;
1917
1918 /* Setup the version specific access functions. */
1919 sframe_set_version (SFRAME_VERSION_2);
1920
1921 /* Process all fdes and create SFrame stack trace information. */
1922 create_sframe_all ();
1923
1924 output_sframe_internal ();
1925 }
1926
1927 #else /* support_sframe_p */
1928
1929 void
1930 output_sframe (segT sframe_seg ATTRIBUTE_UNUSED)
1931 {
1932 }
1933
1934 #endif /* support_sframe_p */
1935