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