Home | History | Annotate | Line # | Download | only in gas
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