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