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