1/* gen-sframe.c - Support for generating SFrame section. 2 Copyright (C) 2022-2024 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 "gen-sframe.h" 25#include "dw2gencfi.h" 26 27#ifdef support_sframe_p 28 29/* By default, use 32-bit relocations from .sframe into .text. */ 30#ifndef SFRAME_RELOC_SIZE 31# define SFRAME_RELOC_SIZE 4 32#endif 33 34/* Whether frame row entries track RA. 35 36 A target may not need return address tracking for stack tracing. If it 37 does need the same, SFRAME_CFA_RA_REG must be defined with the return 38 address register number. */ 39 40#if defined (sframe_ra_tracking_p) && defined (SFRAME_CFA_RA_REG) 41# ifndef SFRAME_FRE_RA_TRACKING 42# define SFRAME_FRE_RA_TRACKING 1 43# endif 44#endif 45 46/* SFrame FRE type selection optimization is an optimization for size. 47 48 There are three flavors of SFrame FRE representation in the binary format: 49 - sframe_frame_row_entry_addr1 where the FRE start address is 1 byte. 50 - sframe_frame_row_entry_addr2 where the FRE start address is 2 bytes. 51 - sframe_frame_row_entry_addr4 where the FRE start address is 4 bytes. 52 53 Note that in the SFrame format, all SFrame FREs of a function use one 54 single representation. The SFrame FRE type itself is identified via the 55 information in the SFrame FDE function info. 56 57 Now, to select the minimum required one from the list above, one needs to 58 make a decision based on the size (in bytes) of the function. 59 60 As a result, for this optimization, some fragments (generated with a new 61 type rs_sframe) for the SFrame section are fixed up later. 62 63 This optimization (for size) is enabled by default. */ 64 65#ifndef SFRAME_FRE_TYPE_SELECTION_OPT 66# define SFRAME_FRE_TYPE_SELECTION_OPT 1 67#endif 68 69/* Emit a single byte into the current segment. */ 70 71static inline void 72out_one (int byte) 73{ 74 FRAG_APPEND_1_CHAR (byte); 75} 76 77/* Emit a two-byte word into the current segment. */ 78 79static inline void 80out_two (int data) 81{ 82 md_number_to_chars (frag_more (2), data, 2); 83} 84 85/* Emit a four byte word into the current segment. */ 86 87static inline void 88out_four (int data) 89{ 90 md_number_to_chars (frag_more (4), data, 4); 91} 92 93/* Get the start address symbol from the DWARF FDE. */ 94 95static symbolS* 96get_dw_fde_start_addrS (const struct fde_entry *dw_fde) 97{ 98 return dw_fde->start_address; 99} 100 101/* Get the start address symbol from the DWARF FDE. */ 102 103static symbolS* 104get_dw_fde_end_addrS (const struct fde_entry *dw_fde) 105{ 106 return dw_fde->end_address; 107} 108 109/* Get whether PAUTH B key is used. */ 110static bool 111get_dw_fde_pauth_b_key_p (const struct fde_entry *dw_fde ATTRIBUTE_UNUSED) 112{ 113#ifdef tc_fde_entry_extras 114 return (dw_fde->pauth_key == AARCH64_PAUTH_KEY_B); 115#else 116 return false; 117#endif 118} 119 120/* SFrame Frame Row Entry (FRE) related functions. */ 121 122static void 123sframe_fre_set_begin_addr (struct sframe_row_entry *fre, symbolS *beginS) 124{ 125 fre->pc_begin = beginS; 126} 127 128static void 129sframe_fre_set_end_addr (struct sframe_row_entry *fre, symbolS *endS) 130{ 131 fre->pc_end = endS; 132} 133 134static void 135sframe_fre_set_cfa_base_reg (struct sframe_row_entry *fre, 136 unsigned int cfa_base_reg) 137{ 138 fre->cfa_base_reg = cfa_base_reg; 139 fre->merge_candidate = false; 140} 141 142static void 143sframe_fre_set_cfa_offset (struct sframe_row_entry *fre, 144 offsetT cfa_offset) 145{ 146 fre->cfa_offset = cfa_offset; 147 fre->merge_candidate = false; 148} 149 150#ifdef SFRAME_FRE_RA_TRACKING 151static void 152sframe_fre_set_ra_track (struct sframe_row_entry *fre, offsetT ra_offset) 153{ 154 fre->ra_loc = SFRAME_FRE_ELEM_LOC_STACK; 155 fre->ra_offset = ra_offset; 156 fre->merge_candidate = false; 157} 158#endif 159 160static void 161sframe_fre_set_bp_track (struct sframe_row_entry *fre, offsetT bp_offset) 162{ 163 fre->bp_loc = SFRAME_FRE_ELEM_LOC_STACK; 164 fre->bp_offset = bp_offset; 165 fre->merge_candidate = false; 166} 167 168/* All stack offset values within an FRE are uniformly encoded in the same 169 number of bytes. The size of the stack offset values will, however, vary 170 across FREs. */ 171 172#define VALUE_8BIT 0x7f 173#define VALUE_16BIT 0x7fff 174#define VALUE_32BIT 0x7fffffff 175#define VALUE_64BIT 0x7fffffffffffffff 176 177/* Given a signed offset, return the size in bytes needed to represent it. */ 178 179static unsigned int 180get_offset_size_in_bytes (offsetT value) 181{ 182 unsigned int size = 0; 183 184 if (value <= VALUE_8BIT && value >= (offsetT) -VALUE_8BIT) 185 size = 1; 186 else if (value <= VALUE_16BIT && value >= (offsetT) -VALUE_16BIT) 187 size = 2; 188 else if (value <= VALUE_32BIT && value >= (offsetT) -VALUE_32BIT) 189 size = 4; 190 else if ((sizeof (offsetT) > 4) && (value <= (offsetT) VALUE_64BIT 191 && value >= (offsetT) -VALUE_64BIT)) 192 size = 8; 193 194 return size; 195} 196 197#define SFRAME_FRE_OFFSET_FUNC_MAP_INDEX_1B 0 /* SFRAME_FRE_OFFSET_1B. */ 198#define SFRAME_FRE_OFFSET_FUNC_MAP_INDEX_2B 1 /* SFRAME_FRE_OFFSET_2B. */ 199#define SFRAME_FRE_OFFSET_FUNC_MAP_INDEX_4B 2 /* SFRAME_FRE_OFFSET_4B. */ 200#define SFRAME_FRE_OFFSET_FUNC_MAP_INDEX_8B 3 /* Not supported in SFrame. */ 201#define SFRAME_FRE_OFFSET_FUNC_MAP_INDEX_MAX SFRAME_FRE_OFFSET_FUNC_MAP_INDEX_8B 202 203/* Helper struct for mapping offset size to output functions. */ 204 205struct sframe_fre_offset_func_map 206{ 207 unsigned int offset_size; 208 void (*out_func)(int); 209}; 210 211/* Given an OFFSET_SIZE, return the size in bytes needed to represent it. */ 212 213static unsigned int 214sframe_fre_offset_func_map_index (unsigned int offset_size) 215{ 216 unsigned int idx = SFRAME_FRE_OFFSET_FUNC_MAP_INDEX_MAX; 217 218 switch (offset_size) 219 { 220 case SFRAME_FRE_OFFSET_1B: 221 idx = SFRAME_FRE_OFFSET_FUNC_MAP_INDEX_1B; 222 break; 223 case SFRAME_FRE_OFFSET_2B: 224 idx = SFRAME_FRE_OFFSET_FUNC_MAP_INDEX_2B; 225 break; 226 case SFRAME_FRE_OFFSET_4B: 227 idx = SFRAME_FRE_OFFSET_FUNC_MAP_INDEX_4B; 228 break; 229 default: 230 /* Not supported in SFrame. */ 231 break; 232 } 233 234 return idx; 235} 236 237/* Mapping from offset size to the output function to emit the value. */ 238 239static const 240struct sframe_fre_offset_func_map 241fre_offset_func_map[SFRAME_FRE_OFFSET_FUNC_MAP_INDEX_MAX+1] = 242{ 243 { SFRAME_FRE_OFFSET_1B, out_one }, 244 { SFRAME_FRE_OFFSET_2B, out_two }, 245 { SFRAME_FRE_OFFSET_4B, out_four }, 246 { -1, NULL } /* Not Supported in SFrame. */ 247}; 248 249/* SFrame version specific operations access. */ 250 251static struct sframe_version_ops sframe_ver_ops; 252 253/* SFrame (SFRAME_VERSION_1) set FRE info. */ 254 255static unsigned char 256sframe_v1_set_fre_info (unsigned int base_reg, unsigned int num_offsets, 257 unsigned int offset_size, bool mangled_ra_p) 258{ 259 unsigned char fre_info; 260 fre_info = SFRAME_V1_FRE_INFO (base_reg, num_offsets, offset_size); 261 fre_info = SFRAME_V1_FRE_INFO_UPDATE_MANGLED_RA_P (mangled_ra_p, fre_info); 262 return fre_info; 263} 264 265/* SFrame (SFRAME_VERSION_1) set function info. */ 266static unsigned char 267sframe_v1_set_func_info (unsigned int fde_type, unsigned int fre_type, 268 unsigned int pauth_key) 269{ 270 unsigned char func_info; 271 func_info = SFRAME_V1_FUNC_INFO (fde_type, fre_type); 272 func_info = SFRAME_V1_FUNC_INFO_UPDATE_PAUTH_KEY (pauth_key, func_info); 273 return func_info; 274} 275 276/* SFrame version specific operations setup. */ 277 278static void 279sframe_set_version (uint32_t sframe_version ATTRIBUTE_UNUSED) 280{ 281 sframe_ver_ops.format_version = SFRAME_VERSION_2; 282 283 /* These operations remain the same for SFRAME_VERSION_2 as fre_info and 284 func_info have not changed from SFRAME_VERSION_1. */ 285 286 sframe_ver_ops.set_fre_info = sframe_v1_set_fre_info; 287 288 sframe_ver_ops.set_func_info = sframe_v1_set_func_info; 289} 290 291/* SFrame set FRE info. */ 292 293static unsigned char 294sframe_set_fre_info (unsigned int base_reg, unsigned int num_offsets, 295 unsigned int offset_size, bool mangled_ra_p) 296{ 297 return sframe_ver_ops.set_fre_info (base_reg, num_offsets, 298 offset_size, mangled_ra_p); 299} 300 301/* SFrame set func info. */ 302 303static unsigned char 304sframe_set_func_info (unsigned int fde_type, unsigned int fre_type, 305 unsigned int pauth_key) 306{ 307 return sframe_ver_ops.set_func_info (fde_type, fre_type, pauth_key); 308} 309 310/* Get the number of SFrame FDEs for the current file. */ 311 312static unsigned int 313get_num_sframe_fdes (void); 314 315/* Get the number of SFrame frame row entries for the current file. */ 316 317static unsigned int 318get_num_sframe_fres (void); 319 320/* Get CFA base register ID as represented in SFrame Frame Row Entry. */ 321 322static unsigned int 323get_fre_base_reg_id (struct sframe_row_entry *sframe_fre) 324{ 325 unsigned int cfi_insn_cfa_base_reg = sframe_fre->cfa_base_reg; 326 unsigned fre_base_reg = SFRAME_BASE_REG_SP; 327 328 if (cfi_insn_cfa_base_reg == SFRAME_CFA_FP_REG) 329 fre_base_reg = SFRAME_BASE_REG_FP; 330 331 /* Only one bit is reserved in SFRAME_VERSION_1. */ 332 gas_assert (fre_base_reg == SFRAME_BASE_REG_SP 333 || fre_base_reg == SFRAME_BASE_REG_FP); 334 335 return fre_base_reg; 336} 337 338/* Get number of offsets necessary for the SFrame Frame Row Entry. */ 339 340static unsigned int 341get_fre_num_offsets (struct sframe_row_entry *sframe_fre) 342{ 343 /* Atleast 1 must always be present (to recover CFA). */ 344 unsigned int fre_num_offsets = 1; 345 346 if (sframe_fre->bp_loc == SFRAME_FRE_ELEM_LOC_STACK) 347 fre_num_offsets++; 348#ifdef SFRAME_FRE_RA_TRACKING 349 if (sframe_fre->ra_loc == SFRAME_FRE_ELEM_LOC_STACK) 350 fre_num_offsets++; 351#endif 352 return fre_num_offsets; 353} 354 355/* Get the minimum necessary offset size (in bytes) for this 356 SFrame frame row entry. */ 357 358static unsigned int 359sframe_get_fre_offset_size (struct sframe_row_entry *sframe_fre) 360{ 361 unsigned int max_offset_size = 0; 362 unsigned int cfa_offset_size = 0; 363 unsigned int bp_offset_size = 0; 364 unsigned int ra_offset_size = 0; 365 366 unsigned int fre_offset_size = 0; 367 368 /* What size of offsets appear in this frame row entry. */ 369 cfa_offset_size = get_offset_size_in_bytes (sframe_fre->cfa_offset); 370 if (sframe_fre->bp_loc == SFRAME_FRE_ELEM_LOC_STACK) 371 bp_offset_size = get_offset_size_in_bytes (sframe_fre->bp_offset); 372#ifdef SFRAME_FRE_RA_TRACKING 373 if (sframe_ra_tracking_p () 374 && sframe_fre->ra_loc == SFRAME_FRE_ELEM_LOC_STACK) 375 ra_offset_size = get_offset_size_in_bytes (sframe_fre->ra_offset); 376#endif 377 378 /* Get the maximum size needed to represent the offsets. */ 379 max_offset_size = cfa_offset_size; 380 if (bp_offset_size > max_offset_size) 381 max_offset_size = bp_offset_size; 382 if (ra_offset_size > max_offset_size) 383 max_offset_size = ra_offset_size; 384 385 gas_assert (max_offset_size); 386 387 switch (max_offset_size) 388 { 389 case 1: 390 fre_offset_size = SFRAME_FRE_OFFSET_1B; 391 break; 392 case 2: 393 fre_offset_size = SFRAME_FRE_OFFSET_2B; 394 break; 395 case 4: 396 fre_offset_size = SFRAME_FRE_OFFSET_4B; 397 break; 398 default: 399 /* Offset of size 8 bytes is not supported in SFrame format 400 version 1. */ 401 as_fatal (_("SFrame unsupported offset value\n")); 402 break; 403 } 404 405 return fre_offset_size; 406} 407 408#if SFRAME_FRE_TYPE_SELECTION_OPT 409 410/* Create a composite expression CEXP (for SFrame FRE start address) such that: 411 412 exp = <val> OP_absent <width>, where, 413 414 - <val> and <width> are themselves expressionS. 415 - <val> stores the expression which when evaluated gives the value of the 416 start address offset of the FRE. 417 - <width> stores the expression when evaluated gives the number of bytes 418 needed to encode the start address offset of the FRE. 419 420 The use of OP_absent as the X_op_symbol helps identify this expression 421 later when fragments are fixed up. */ 422 423static void 424create_fre_start_addr_exp (expressionS *cexp, symbolS *fre_pc_begin, 425 symbolS *fde_start_address, 426 symbolS *fde_end_address) 427{ 428 expressionS val; 429 expressionS width; 430 431 /* val expression stores the FDE start address offset from the start PC 432 of function. */ 433 val.X_op = O_subtract; 434 val.X_add_symbol = fre_pc_begin; 435 val.X_op_symbol = fde_start_address; 436 val.X_add_number = 0; 437 438 /* width expressions stores the size of the function. This is used later 439 to determine the number of bytes to be used to encode the FRE start 440 address of each FRE of the function. */ 441 width.X_op = O_subtract; 442 width.X_add_symbol = fde_end_address; 443 width.X_op_symbol = fde_start_address; 444 width.X_add_number = 0; 445 446 cexp->X_op = O_absent; 447 cexp->X_add_symbol = make_expr_symbol (&val); 448 cexp->X_op_symbol = make_expr_symbol (&width); 449 cexp->X_add_number = 0; 450} 451 452/* Create a composite expression CEXP (for SFrame FDE function info) such that: 453 454 exp = <rest_of_func_info> OP_modulus <width>, where, 455 456 - <rest_of_func_info> and <width> are themselves expressionS. 457 - <rest_of_func_info> stores a constant expression where X_add_number is 458 used to stash away the func_info. The upper 4-bits of the func_info are copied 459 back to the resulting byte by the fragment fixup logic. 460 - <width> stores the expression when evaluated gives the size of the 461 function in number of bytes. 462 463 The use of OP_modulus as the X_op_symbol helps identify this expression 464 later when fragments are fixed up. */ 465 466static void 467create_func_info_exp (expressionS *cexp, symbolS *dw_fde_end_addrS, 468 symbolS *dw_fde_start_addrS, uint8_t func_info) 469{ 470 expressionS width; 471 expressionS rest_of_func_info; 472 473 width.X_op = O_subtract; 474 width.X_add_symbol = dw_fde_end_addrS; 475 width.X_op_symbol = dw_fde_start_addrS; 476 width.X_add_number = 0; 477 478 rest_of_func_info.X_op = O_constant; 479 rest_of_func_info.X_add_number = func_info; 480 481 cexp->X_op = O_modulus; 482 cexp->X_add_symbol = make_expr_symbol (&rest_of_func_info); 483 cexp->X_op_symbol = make_expr_symbol (&width); 484 cexp->X_add_number = 0; 485} 486 487#endif 488 489static void 490output_sframe_row_entry (symbolS *fde_start_addr, 491 symbolS *fde_end_addr, 492 struct sframe_row_entry *sframe_fre) 493{ 494 unsigned char fre_info; 495 unsigned int fre_num_offsets; 496 unsigned int fre_offset_size; 497 unsigned int fre_base_reg; 498 expressionS exp; 499 unsigned int fre_addr_size; 500 501 unsigned int idx = 0; 502 unsigned int fre_write_offsets = 0; 503 504 fre_addr_size = 4; /* 4 bytes by default. FIXME tie it to fre_type? */ 505 506 /* SFrame FRE Start Address. */ 507#if SFRAME_FRE_TYPE_SELECTION_OPT 508 create_fre_start_addr_exp (&exp, sframe_fre->pc_begin, fde_start_addr, 509 fde_end_addr); 510 frag_grow (fre_addr_size); 511 frag_var (rs_sframe, fre_addr_size, 0, (relax_substateT) 0, 512 make_expr_symbol (&exp), 0, (char *) frag_now); 513#else 514 gas_assert (fde_end_addr); 515 exp.X_op = O_subtract; 516 exp.X_add_symbol = sframe_fre->pc_begin; /* to. */ 517 exp.X_op_symbol = fde_start_addr; /* from. */ 518 exp.X_add_number = 0; 519 emit_expr (&exp, fre_addr_size); 520#endif 521 522 /* Create the fre_info using the CFA base register, number of offsets and max 523 size of offset in this frame row entry. */ 524 fre_base_reg = get_fre_base_reg_id (sframe_fre); 525 fre_num_offsets = get_fre_num_offsets (sframe_fre); 526 fre_offset_size = sframe_get_fre_offset_size (sframe_fre); 527 fre_info = sframe_set_fre_info (fre_base_reg, fre_num_offsets, 528 fre_offset_size, sframe_fre->mangled_ra_p); 529 out_one (fre_info); 530 531 idx = sframe_fre_offset_func_map_index (fre_offset_size); 532 gas_assert (idx < SFRAME_FRE_OFFSET_FUNC_MAP_INDEX_MAX); 533 534 /* Write out the offsets in order - cfa, bp, ra. */ 535 fre_offset_func_map[idx].out_func (sframe_fre->cfa_offset); 536 fre_write_offsets++; 537 538#ifdef SFRAME_FRE_RA_TRACKING 539 if (sframe_fre->ra_loc == SFRAME_FRE_ELEM_LOC_STACK) 540 { 541 fre_offset_func_map[idx].out_func (sframe_fre->ra_offset); 542 fre_write_offsets++; 543 } 544#endif 545 if (sframe_fre->bp_loc == SFRAME_FRE_ELEM_LOC_STACK) 546 { 547 fre_offset_func_map[idx].out_func (sframe_fre->bp_offset); 548 fre_write_offsets++; 549 } 550 551 /* Check if the expected number offsets have been written out 552 in this FRE. */ 553 gas_assert (fre_write_offsets == fre_num_offsets); 554} 555 556static void 557output_sframe_funcdesc (symbolS *start_of_fre_section, 558 symbolS *fre_symbol, 559 struct sframe_func_entry *sframe_fde) 560{ 561 expressionS exp; 562 unsigned int addr_size; 563 symbolS *dw_fde_start_addrS, *dw_fde_end_addrS; 564 unsigned int pauth_key; 565 566 addr_size = SFRAME_RELOC_SIZE; 567 dw_fde_start_addrS = get_dw_fde_start_addrS (sframe_fde->dw_fde); 568 dw_fde_end_addrS = get_dw_fde_end_addrS (sframe_fde->dw_fde); 569 570 /* Start address of the function. */ 571 exp.X_op = O_subtract; 572 exp.X_add_symbol = dw_fde_start_addrS; /* to location. */ 573 exp.X_op_symbol = symbol_temp_new_now (); /* from location. */ 574 exp.X_add_number = 0; 575 emit_expr (&exp, addr_size); 576 577 /* Size of the function in bytes. */ 578 exp.X_op = O_subtract; 579 exp.X_add_symbol = dw_fde_end_addrS; 580 exp.X_op_symbol = dw_fde_start_addrS; 581 exp.X_add_number = 0; 582 emit_expr (&exp, addr_size); 583 584 /* Offset to the first frame row entry. */ 585 exp.X_op = O_subtract; 586 exp.X_add_symbol = fre_symbol; /* Minuend. */ 587 exp.X_op_symbol = start_of_fre_section; /* Subtrahend. */ 588 exp.X_add_number = 0; 589 emit_expr (&exp, addr_size); 590 591 /* Number of FREs. */ 592 out_four (sframe_fde->num_fres); 593 594 /* SFrame FDE function info. */ 595 unsigned char func_info; 596 pauth_key = (get_dw_fde_pauth_b_key_p (sframe_fde->dw_fde) 597 ? SFRAME_AARCH64_PAUTH_KEY_B : SFRAME_AARCH64_PAUTH_KEY_A); 598 func_info = sframe_set_func_info (SFRAME_FDE_TYPE_PCINC, 599 SFRAME_FRE_TYPE_ADDR4, 600 pauth_key); 601#if SFRAME_FRE_TYPE_SELECTION_OPT 602 expressionS cexp; 603 create_func_info_exp (&cexp, dw_fde_end_addrS, dw_fde_start_addrS, 604 func_info); 605 frag_grow (1); /* Size of func info is unsigned char. */ 606 frag_var (rs_sframe, 1, 0, (relax_substateT) 0, 607 make_expr_symbol (&cexp), 0, (char *) frag_now); 608#else 609 out_one (func_info); 610#endif 611 out_one (0); 612 out_two (0); 613} 614 615static void 616output_sframe_internal (void) 617{ 618 expressionS exp; 619 unsigned int i = 0; 620 621 symbolS *end_of_frame_hdr; 622 symbolS *end_of_frame_section; 623 symbolS *start_of_func_desc_section; 624 symbolS *start_of_fre_section; 625 struct sframe_func_entry *sframe_fde; 626 struct sframe_row_entry *sframe_fre; 627 unsigned char abi_arch = 0; 628 int fixed_bp_offset = SFRAME_CFA_FIXED_FP_INVALID; 629 int fixed_ra_offset = SFRAME_CFA_FIXED_RA_INVALID; 630 unsigned int addr_size; 631 632 addr_size = SFRAME_RELOC_SIZE; 633 634 /* The function descriptor entries as dumped by the assembler are not 635 sorted on PCs. */ 636 unsigned char sframe_flags = 0; 637 sframe_flags |= !SFRAME_F_FDE_SORTED; 638 639 unsigned int num_fdes = get_num_sframe_fdes (); 640 unsigned int num_fres = get_num_sframe_fres (); 641 symbolS **fre_symbols = XNEWVEC (symbolS *, num_fres); 642 for (i = 0; i < num_fres; i++) 643 fre_symbols[i] = symbol_temp_make (); 644 645 end_of_frame_hdr = symbol_temp_make (); 646 start_of_fre_section = symbol_temp_make (); 647 start_of_func_desc_section = symbol_temp_make (); 648 end_of_frame_section = symbol_temp_make (); 649 650 /* Output the preamble of SFrame section. */ 651 out_two (SFRAME_MAGIC); 652 out_one (SFRAME_VERSION); 653 out_one (sframe_flags); 654 /* abi/arch. */ 655#ifdef sframe_get_abi_arch 656 abi_arch = sframe_get_abi_arch (); 657#endif 658 gas_assert (abi_arch); 659 out_one (abi_arch); 660 661 /* Offset for the BP register from CFA. Neither of the AMD64 or AAPCS64 662 ABIs have a fixed offset for the BP register from the CFA. This may be 663 useful in future (but not without additional support in the toolchain) 664 for specialized handling/encoding for cases where, for example, 665 -fno-omit-frame-pointer is used. */ 666 out_one (fixed_bp_offset); 667 668 /* Offset for the return address from CFA is fixed for some ABIs 669 (e.g., AMD64), output a SFRAME_CFA_FIXED_RA_INVALID otherwise. */ 670#ifdef sframe_ra_tracking_p 671 if (!sframe_ra_tracking_p ()) 672 fixed_ra_offset = sframe_cfa_ra_offset (); 673#endif 674 out_one (fixed_ra_offset); 675 676 /* None of the AMD64, or AARCH64 ABIs need the auxiliary header. 677 When the need does arise to use this field, the appropriate backend 678 must provide this information. */ 679 out_one (0); /* Auxiliary SFrame header length. */ 680 681 out_four (num_fdes); /* Number of FDEs. */ 682 out_four (num_fres); /* Number of FREs. */ 683 684 /* FRE sub-section len. */ 685 exp.X_op = O_subtract; 686 exp.X_add_symbol = end_of_frame_section; 687 exp.X_op_symbol = start_of_fre_section; 688 exp.X_add_number = 0; 689 emit_expr (&exp, addr_size); 690 691 /* Offset of Function Index sub-section. */ 692 exp.X_op = O_subtract; 693 exp.X_add_symbol = end_of_frame_hdr; 694 exp.X_op_symbol = start_of_func_desc_section; 695 exp.X_add_number = 0; 696 emit_expr (&exp, addr_size); 697 698 /* Offset of FRE sub-section. */ 699 exp.X_op = O_subtract; 700 exp.X_add_symbol = start_of_fre_section; 701 exp.X_op_symbol = end_of_frame_hdr; 702 exp.X_add_number = 0; 703 emit_expr (&exp, addr_size); 704 705 symbol_set_value_now (end_of_frame_hdr); 706 symbol_set_value_now (start_of_func_desc_section); 707 708 /* Output the SFrame function descriptor entries. */ 709 i = 0; 710 for (sframe_fde = all_sframe_fdes; sframe_fde; sframe_fde = sframe_fde->next) 711 { 712 output_sframe_funcdesc (start_of_fre_section, 713 fre_symbols[i], sframe_fde); 714 i += sframe_fde->num_fres; 715 } 716 717 symbol_set_value_now (start_of_fre_section); 718 719 /* Output the SFrame FREs. */ 720 i = 0; 721 sframe_fde = all_sframe_fdes; 722 723 for (sframe_fde = all_sframe_fdes; sframe_fde; sframe_fde = sframe_fde->next) 724 { 725 for (sframe_fre = sframe_fde->sframe_fres; 726 sframe_fre; 727 sframe_fre = sframe_fre->next) 728 { 729 symbol_set_value_now (fre_symbols[i]); 730 output_sframe_row_entry (get_dw_fde_start_addrS (sframe_fde->dw_fde), 731 get_dw_fde_end_addrS (sframe_fde->dw_fde), 732 sframe_fre); 733 i++; 734 } 735 } 736 737 symbol_set_value_now (end_of_frame_section); 738 739 gas_assert (i == num_fres); 740 741 free (fre_symbols); 742 fre_symbols = NULL; 743} 744 745/* List of SFrame FDE entries. */ 746 747struct sframe_func_entry *all_sframe_fdes; 748 749/* Tail of the list to add to. */ 750 751static struct sframe_func_entry **last_sframe_fde = &all_sframe_fdes; 752 753static unsigned int 754get_num_sframe_fdes (void) 755{ 756 struct sframe_func_entry *sframe_fde; 757 unsigned int total_fdes = 0; 758 759 for (sframe_fde = all_sframe_fdes; sframe_fde ; sframe_fde = sframe_fde->next) 760 total_fdes++; 761 762 return total_fdes; 763} 764 765/* Get the total number of SFrame row entries across the FDEs. */ 766 767static unsigned int 768get_num_sframe_fres (void) 769{ 770 struct sframe_func_entry *sframe_fde; 771 unsigned int total_fres = 0; 772 773 for (sframe_fde = all_sframe_fdes; sframe_fde ; sframe_fde = sframe_fde->next) 774 total_fres += sframe_fde->num_fres; 775 776 return total_fres; 777} 778 779/* Allocate an SFrame FDE. */ 780 781static struct sframe_func_entry* 782sframe_fde_alloc (void) 783{ 784 struct sframe_func_entry *sframe_fde = XCNEW (struct sframe_func_entry); 785 return sframe_fde; 786} 787 788/* Link the SFrame FDE in. */ 789 790static int 791sframe_fde_link (struct sframe_func_entry *sframe_fde) 792{ 793 *last_sframe_fde = sframe_fde; 794 last_sframe_fde = &sframe_fde->next; 795 796 return 0; 797} 798 799/* Free up the SFrame FDE. */ 800 801static void 802sframe_fde_free (struct sframe_func_entry *sframe_fde) 803{ 804 XDELETE (sframe_fde); 805 sframe_fde = NULL; 806} 807 808/* SFrame translation context functions. */ 809 810/* Allocate a new SFrame translation context. */ 811 812static struct sframe_xlate_ctx* 813sframe_xlate_ctx_alloc (void) 814{ 815 struct sframe_xlate_ctx* xlate_ctx = XCNEW (struct sframe_xlate_ctx); 816 return xlate_ctx; 817} 818 819/* Initialize the given SFrame translation context. */ 820 821static void 822sframe_xlate_ctx_init (struct sframe_xlate_ctx *xlate_ctx) 823{ 824 xlate_ctx->dw_fde = NULL; 825 xlate_ctx->first_fre = NULL; 826 xlate_ctx->last_fre = NULL; 827 xlate_ctx->cur_fre = NULL; 828 xlate_ctx->remember_fre = NULL; 829 xlate_ctx->num_xlate_fres = 0; 830} 831 832/* Cleanup the given SFrame translation context. */ 833 834static void 835sframe_xlate_ctx_cleanup (struct sframe_xlate_ctx *xlate_ctx) 836{ 837 struct sframe_row_entry *fre, *fre_next; 838 839 if (xlate_ctx->num_xlate_fres) 840 { 841 fre = xlate_ctx->first_fre; 842 while (fre) 843 { 844 fre_next = fre->next; 845 XDELETE (fre); 846 fre = fre_next; 847 } 848 } 849 850 sframe_xlate_ctx_init (xlate_ctx); 851} 852 853/* Transfer the state from the SFrame translation context to the SFrame FDE. */ 854 855static void 856sframe_xlate_ctx_finalize (struct sframe_xlate_ctx *xlate_ctx, 857 struct sframe_func_entry *sframe_fde) 858{ 859 sframe_fde->dw_fde = xlate_ctx->dw_fde; 860 sframe_fde->sframe_fres = xlate_ctx->first_fre; 861 sframe_fde->num_fres = xlate_ctx->num_xlate_fres; 862} 863 864static struct sframe_row_entry* 865sframe_row_entry_new (void) 866{ 867 struct sframe_row_entry *fre = XCNEW (struct sframe_row_entry); 868 /* Reset cfa_base_reg to -1. A value of 0 will imply some valid register 869 for the supported arches. */ 870 fre->cfa_base_reg = -1; 871 fre->merge_candidate = true; 872 /* Reset the mangled RA status bit to zero by default. We will initialize it in 873 sframe_row_entry_initialize () with the sticky bit if set. */ 874 fre->mangled_ra_p = false; 875 876 return fre; 877} 878 879/* Add the given FRE in the list of frame row entries in the given FDE 880 translation context. */ 881 882static void 883sframe_xlate_ctx_add_fre (struct sframe_xlate_ctx *xlate_ctx, 884 struct sframe_row_entry *fre) 885{ 886 gas_assert (xlate_ctx && fre); 887 888 /* Add the frame row entry. */ 889 if (!xlate_ctx->first_fre) 890 xlate_ctx->first_fre = fre; 891 else if (xlate_ctx->last_fre) 892 xlate_ctx->last_fre->next = fre; 893 894 xlate_ctx->last_fre = fre; 895 896 /* Keep track of the total number of SFrame frame row entries. */ 897 xlate_ctx->num_xlate_fres++; 898} 899 900/* A SFrame Frame Row Entry is self-sufficient in terms of stack tracing info 901 for a given PC. It contains information assimilated from multiple CFI 902 instructions, and hence, a new SFrame FRE is initialized with the data from 903 the previous known FRE, if any. 904 905 Understandably, not all information (especially the instruction begin 906 and end boundaries) needs to be relayed. Hence, the caller of this API 907 must set the pc_begin and pc_end as applicable. */ 908 909static void 910sframe_row_entry_initialize (struct sframe_row_entry *cur_fre, 911 struct sframe_row_entry *prev_fre) 912{ 913 gas_assert (prev_fre); 914 cur_fre->cfa_base_reg = prev_fre->cfa_base_reg; 915 cur_fre->cfa_offset = prev_fre->cfa_offset; 916 cur_fre->bp_loc = prev_fre->bp_loc; 917 cur_fre->bp_offset = prev_fre->bp_offset; 918 cur_fre->ra_loc = prev_fre->ra_loc; 919 cur_fre->ra_offset = prev_fre->ra_offset; 920 /* Treat RA mangling as a sticky bit. It retains its value until another 921 .cfi_negate_ra_state is seen. */ 922 cur_fre->mangled_ra_p = prev_fre->mangled_ra_p; 923} 924 925/* Translate DW_CFA_advance_loc into SFrame context. 926 Return SFRAME_XLATE_OK if success. */ 927 928static int 929sframe_xlate_do_advance_loc (struct sframe_xlate_ctx *xlate_ctx, 930 struct cfi_insn_data *cfi_insn) 931{ 932 struct sframe_row_entry *last_fre = xlate_ctx->last_fre; 933 /* Get the scratchpad FRE currently being updated as the cfi_insn's 934 get interpreted. This FRE eventually gets linked in into the 935 list of FREs for the specific function. */ 936 struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre; 937 938 if (cur_fre) 939 { 940 if (!cur_fre->merge_candidate) 941 { 942 sframe_fre_set_end_addr (cur_fre, cfi_insn->u.ll.lab2); 943 944 sframe_xlate_ctx_add_fre (xlate_ctx, cur_fre); 945 last_fre = xlate_ctx->last_fre; 946 947 xlate_ctx->cur_fre = sframe_row_entry_new (); 948 cur_fre = xlate_ctx->cur_fre; 949 950 if (last_fre) 951 sframe_row_entry_initialize (cur_fre, last_fre); 952 } 953 else 954 { 955 sframe_fre_set_end_addr (last_fre, cfi_insn->u.ll.lab2); 956 gas_assert (last_fre->merge_candidate == false); 957 } 958 } 959 else 960 { 961 xlate_ctx->cur_fre = sframe_row_entry_new (); 962 cur_fre = xlate_ctx->cur_fre; 963 } 964 965 gas_assert (cur_fre); 966 sframe_fre_set_begin_addr (cur_fre, cfi_insn->u.ll.lab2); 967 968 return SFRAME_XLATE_OK; 969} 970 971/* Translate DW_CFA_def_cfa into SFrame context. 972 Return SFRAME_XLATE_OK if success. */ 973 974static int 975sframe_xlate_do_def_cfa (struct sframe_xlate_ctx *xlate_ctx, 976 struct cfi_insn_data *cfi_insn) 977 978{ 979 /* Get the scratchpad FRE. This FRE will eventually get linked in. */ 980 struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre; 981 if (!cur_fre) 982 { 983 xlate_ctx->cur_fre = sframe_row_entry_new (); 984 cur_fre = xlate_ctx->cur_fre; 985 sframe_fre_set_begin_addr (cur_fre, 986 get_dw_fde_start_addrS (xlate_ctx->dw_fde)); 987 } 988 /* Define the current CFA rule to use the provided register and 989 offset. */ 990 sframe_fre_set_cfa_base_reg (cur_fre, cfi_insn->u.ri.reg); 991 sframe_fre_set_cfa_offset (cur_fre, cfi_insn->u.ri.offset); 992 cur_fre->merge_candidate = false; 993 994 return SFRAME_XLATE_OK; 995} 996 997/* Translate DW_CFA_def_cfa_register into SFrame context. 998 Return SFRAME_XLATE_OK if success. */ 999 1000static int 1001sframe_xlate_do_def_cfa_register (struct sframe_xlate_ctx *xlate_ctx, 1002 struct cfi_insn_data *cfi_insn) 1003{ 1004 struct sframe_row_entry *last_fre = xlate_ctx->last_fre; 1005 /* Get the scratchpad FRE. This FRE will eventually get linked in. */ 1006 struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre; 1007 gas_assert (cur_fre); 1008 /* Define the current CFA rule to use the provided register (but to 1009 keep the old offset). */ 1010 sframe_fre_set_cfa_base_reg (cur_fre, cfi_insn->u.ri.reg); 1011 sframe_fre_set_cfa_offset (cur_fre, last_fre->cfa_offset); 1012 cur_fre->merge_candidate = false; 1013 1014 return SFRAME_XLATE_OK; 1015} 1016 1017/* Translate DW_CFA_def_cfa_offset into SFrame context. 1018 Return SFRAME_XLATE_OK if success. */ 1019 1020static int 1021sframe_xlate_do_def_cfa_offset (struct sframe_xlate_ctx *xlate_ctx, 1022 struct cfi_insn_data *cfi_insn) 1023{ 1024 /* The scratchpad FRE currently being updated with each cfi_insn 1025 being interpreted. This FRE eventually gets linked in into the 1026 list of FREs for the specific function. */ 1027 struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre; 1028 1029 gas_assert (cur_fre); 1030 /* Define the current CFA rule to use the provided offset (but to keep 1031 the old register). However, if the old register is not FP/SP, 1032 skip creating SFrame stack trace info for the function. */ 1033 if ((cur_fre->cfa_base_reg == SFRAME_CFA_FP_REG) 1034 || (cur_fre->cfa_base_reg == SFRAME_CFA_SP_REG)) 1035 { 1036 sframe_fre_set_cfa_offset (cur_fre, cfi_insn->u.i); 1037 cur_fre->merge_candidate = false; 1038 } 1039 else 1040 return SFRAME_XLATE_ERR_NOTREPRESENTED; 1041 1042 return SFRAME_XLATE_OK; 1043} 1044 1045/* Translate DW_CFA_offset into SFrame context. 1046 Return SFRAME_XLATE_OK if success. */ 1047 1048static int 1049sframe_xlate_do_offset (struct sframe_xlate_ctx *xlate_ctx, 1050 struct cfi_insn_data *cfi_insn) 1051{ 1052 /* The scratchpad FRE currently being updated with each cfi_insn 1053 being interpreted. This FRE eventually gets linked in into the 1054 list of FREs for the specific function. */ 1055 struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre; 1056 1057 gas_assert (cur_fre); 1058 /* Change the rule for the register indicated by the register number to 1059 be the specified offset. */ 1060 if (cfi_insn->u.r == SFRAME_CFA_FP_REG) 1061 { 1062 gas_assert (!cur_fre->base_reg); 1063 sframe_fre_set_bp_track (cur_fre, cfi_insn->u.ri.offset); 1064 cur_fre->merge_candidate = false; 1065 } 1066#ifdef SFRAME_FRE_RA_TRACKING 1067 else if (sframe_ra_tracking_p () 1068 && cfi_insn->u.r == SFRAME_CFA_RA_REG) 1069 { 1070 sframe_fre_set_ra_track (cur_fre, cfi_insn->u.ri.offset); 1071 cur_fre->merge_candidate = false; 1072 } 1073#endif 1074 /* This is used to track changes to non-rsp registers, skip all others 1075 except FP / RA for now. */ 1076 return SFRAME_XLATE_OK; 1077} 1078 1079/* Translate DW_CFA_val_offset into SFrame context. 1080 Return SFRAME_XLATE_OK if success. */ 1081 1082static int 1083sframe_xlate_do_val_offset (struct sframe_xlate_ctx *xlate_ctx ATTRIBUTE_UNUSED, 1084 struct cfi_insn_data *cfi_insn) 1085{ 1086 /* Previous value of register is CFA + offset. However, if the specified 1087 register is not interesting (FP or RA reg), the current DW_CFA_val_offset 1088 instruction can be safely skipped without sacrificing the asynchronicity of 1089 stack trace information. */ 1090 if (cfi_insn->u.r == SFRAME_CFA_FP_REG) 1091 return SFRAME_XLATE_ERR_NOTREPRESENTED; /* Not represented. */ 1092#ifdef SFRAME_FRE_RA_TRACKING 1093 else if (sframe_ra_tracking_p () 1094 && cfi_insn->u.r == SFRAME_CFA_RA_REG) 1095 return SFRAME_XLATE_ERR_NOTREPRESENTED; /* Not represented. */ 1096#endif 1097 1098 /* Safe to skip. */ 1099 return SFRAME_XLATE_OK; 1100} 1101 1102/* Translate DW_CFA_remember_state into SFrame context. 1103 Return SFRAME_XLATE_OK if success. */ 1104 1105static int 1106sframe_xlate_do_remember_state (struct sframe_xlate_ctx *xlate_ctx) 1107{ 1108 struct sframe_row_entry *last_fre = xlate_ctx->last_fre; 1109 1110 /* If there is no FRE state to remember, nothing to do here. Return 1111 early with non-zero error code, this will cause no SFrame stack trace 1112 info for the function involved. */ 1113 if (!last_fre) 1114 return SFRAME_XLATE_ERR_INVAL; 1115 1116 if (!xlate_ctx->remember_fre) 1117 xlate_ctx->remember_fre = sframe_row_entry_new (); 1118 sframe_row_entry_initialize (xlate_ctx->remember_fre, last_fre); 1119 1120 return SFRAME_XLATE_OK; 1121} 1122 1123/* Translate DW_CFA_restore_state into SFrame context. 1124 Return SFRAME_XLATE_OK if success. */ 1125 1126static int 1127sframe_xlate_do_restore_state (struct sframe_xlate_ctx *xlate_ctx) 1128{ 1129 /* The scratchpad FRE currently being updated with each cfi_insn 1130 being interpreted. This FRE eventually gets linked in into the 1131 list of FREs for the specific function. */ 1132 struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre; 1133 1134 gas_assert (xlate_ctx->remember_fre); 1135 gas_assert (cur_fre && cur_fre->merge_candidate); 1136 1137 /* Get the CFA state from the DW_CFA_remember_state insn. */ 1138 sframe_row_entry_initialize (cur_fre, xlate_ctx->remember_fre); 1139 /* The PC boundaries of the current SFrame FRE are updated 1140 via other machinery. */ 1141 cur_fre->merge_candidate = false; 1142 return SFRAME_XLATE_OK; 1143} 1144 1145/* Translate DW_CFA_restore into SFrame context. 1146 Return SFRAME_XLATE_OK if success. */ 1147 1148static int 1149sframe_xlate_do_restore (struct sframe_xlate_ctx *xlate_ctx, 1150 struct cfi_insn_data *cfi_insn) 1151{ 1152 struct sframe_row_entry *cie_fre = xlate_ctx->first_fre; 1153 /* The scratchpad FRE currently being updated with each cfi_insn 1154 being interpreted. This FRE eventually gets linked in into the 1155 list of FREs for the specific function. */ 1156 struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre; 1157 1158 /* Change the rule for the indicated register to the rule assigned to 1159 it by the initial_instructions in the CIE. */ 1160 gas_assert (cie_fre); 1161 /* SFrame FREs track only CFA and FP / RA for backtracing purposes; 1162 skip the other .cfi_restore directives. */ 1163 if (cfi_insn->u.r == SFRAME_CFA_FP_REG) 1164 { 1165 gas_assert (cur_fre); 1166 cur_fre->bp_loc = cie_fre->bp_loc; 1167 cur_fre->bp_offset = cie_fre->bp_offset; 1168 cur_fre->merge_candidate = false; 1169 } 1170#ifdef SFRAME_FRE_RA_TRACKING 1171 else if (sframe_ra_tracking_p () 1172 && cfi_insn->u.r == SFRAME_CFA_RA_REG) 1173 { 1174 gas_assert (cur_fre); 1175 cur_fre->ra_loc = cie_fre->ra_loc; 1176 cur_fre->ra_offset = cie_fre->ra_offset; 1177 cur_fre->merge_candidate = false; 1178 } 1179#endif 1180 return SFRAME_XLATE_OK; 1181} 1182 1183/* Translate DW_CFA_GNU_window_save into SFrame context. 1184 Return SFRAME_XLATE_OK if success. */ 1185 1186static int 1187sframe_xlate_do_gnu_window_save (struct sframe_xlate_ctx *xlate_ctx, 1188 struct cfi_insn_data *cfi_insn ATTRIBUTE_UNUSED) 1189{ 1190 struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre; 1191 1192 gas_assert (cur_fre); 1193 /* Toggle the mangled RA status bit. */ 1194 cur_fre->mangled_ra_p = !cur_fre->mangled_ra_p; 1195 cur_fre->merge_candidate = false; 1196 1197 return SFRAME_XLATE_OK; 1198} 1199 1200/* Process CFI_INSN and update the translation context with the FRE 1201 information. 1202 1203 Returns an error code (sframe_xlate_err) if CFI_INSN is not successfully 1204 processed. */ 1205 1206static int 1207sframe_do_cfi_insn (struct sframe_xlate_ctx *xlate_ctx, 1208 struct cfi_insn_data *cfi_insn) 1209{ 1210 int err = 0; 1211 1212 /* Atleast one cfi_insn per FDE is expected. */ 1213 gas_assert (cfi_insn); 1214 int op = cfi_insn->insn; 1215 1216 switch (op) 1217 { 1218 case DW_CFA_advance_loc: 1219 err = sframe_xlate_do_advance_loc (xlate_ctx, cfi_insn); 1220 break; 1221 case DW_CFA_def_cfa: 1222 err = sframe_xlate_do_def_cfa (xlate_ctx, cfi_insn); 1223 break; 1224 case DW_CFA_def_cfa_register: 1225 err = sframe_xlate_do_def_cfa_register (xlate_ctx, cfi_insn); 1226 break; 1227 case DW_CFA_def_cfa_offset: 1228 err = sframe_xlate_do_def_cfa_offset (xlate_ctx, cfi_insn); 1229 break; 1230 case DW_CFA_offset: 1231 err = sframe_xlate_do_offset (xlate_ctx, cfi_insn); 1232 break; 1233 case DW_CFA_val_offset: 1234 err = sframe_xlate_do_val_offset (xlate_ctx, cfi_insn); 1235 break; 1236 case DW_CFA_remember_state: 1237 err = sframe_xlate_do_remember_state (xlate_ctx); 1238 break; 1239 case DW_CFA_restore_state: 1240 err = sframe_xlate_do_restore_state (xlate_ctx); 1241 break; 1242 case DW_CFA_restore: 1243 err = sframe_xlate_do_restore (xlate_ctx, cfi_insn); 1244 break; 1245 /* DW_CFA_AARCH64_negate_ra_state is multiplexed with 1246 DW_CFA_GNU_window_save. */ 1247 case DW_CFA_GNU_window_save: 1248 err = sframe_xlate_do_gnu_window_save (xlate_ctx, cfi_insn); 1249 break; 1250 /* Other CFI opcodes are not processed at this time. 1251 These do not impact the coverage of the basic stack tracing 1252 information as conveyed in the SFrame format. 1253 - DW_CFA_register, 1254 - etc. */ 1255 case DW_CFA_register: 1256 if (cfi_insn->u.rr.reg1 == SFRAME_CFA_SP_REG 1257#ifdef SFRAME_FRE_RA_TRACKING 1258 || cfi_insn->u.rr.reg1 == SFRAME_CFA_RA_REG 1259#endif 1260 || cfi_insn->u.rr.reg1 == SFRAME_CFA_FP_REG) 1261 err = SFRAME_XLATE_ERR_NOTREPRESENTED; 1262 break; 1263 case DW_CFA_undefined: 1264 case DW_CFA_same_value: 1265 break; 1266 default: 1267 /* Following skipped operations do, however, impact the asynchronicity: 1268 - CFI_escape. */ 1269 err = SFRAME_XLATE_ERR_NOTREPRESENTED; 1270 } 1271 1272 /* An error here will cause no SFrame FDE later. Warn the user because this 1273 will affect the overall coverage and hence, asynchronicity. */ 1274 if (err) 1275 as_warn (_("skipping SFrame FDE due to DWARF CFI op %#x"), op); 1276 1277 return err; 1278} 1279 1280 1281static int 1282sframe_do_fde (struct sframe_xlate_ctx *xlate_ctx, 1283 const struct fde_entry *dw_fde) 1284{ 1285 struct cfi_insn_data *cfi_insn; 1286 int err = SFRAME_XLATE_OK; 1287 1288 xlate_ctx->dw_fde = dw_fde; 1289 1290 /* If the return column is not RIP, SFrame format cannot represent it. */ 1291 if (xlate_ctx->dw_fde->return_column != DWARF2_DEFAULT_RETURN_COLUMN) 1292 return SFRAME_XLATE_ERR_NOTREPRESENTED; 1293 1294 /* Iterate over the CFIs and create SFrame FREs. */ 1295 for (cfi_insn = dw_fde->data; cfi_insn; cfi_insn = cfi_insn->next) 1296 { 1297 /* Translate each CFI, and buffer the state in translation context. */ 1298 err = sframe_do_cfi_insn (xlate_ctx, cfi_insn); 1299 if (err != SFRAME_XLATE_OK) 1300 { 1301 /* Skip generating SFrame stack trace info for the function if any 1302 offending CFI is encountered by sframe_do_cfi_insn (). */ 1303 return err; /* Return the error code. */ 1304 } 1305 } 1306 1307 /* No errors encountered. */ 1308 1309 /* Link in the scratchpad FRE that the last few CFI insns helped create. */ 1310 if (xlate_ctx->cur_fre) 1311 { 1312 sframe_xlate_ctx_add_fre (xlate_ctx, xlate_ctx->cur_fre); 1313 xlate_ctx->cur_fre = NULL; 1314 } 1315 /* Designate the end of the last SFrame FRE. */ 1316 if (xlate_ctx->last_fre) 1317 { 1318 xlate_ctx->last_fre->pc_end 1319 = get_dw_fde_end_addrS (xlate_ctx->dw_fde); 1320 } 1321 1322 return SFRAME_XLATE_OK; 1323} 1324 1325/* Create SFrame stack trace info for all functions. 1326 1327 This function consumes the already generated DWARF FDEs (by dw2gencfi) and 1328 generates data which is later emitted as stack trace information encoded in 1329 the SFrame format. */ 1330 1331static void 1332create_sframe_all (void) 1333{ 1334 struct fde_entry *dw_fde = NULL; 1335 struct sframe_func_entry *sframe_fde = NULL; 1336 1337 struct sframe_xlate_ctx *xlate_ctx = sframe_xlate_ctx_alloc (); 1338 1339 for (dw_fde = all_fde_data; dw_fde ; dw_fde = dw_fde->next) 1340 { 1341 sframe_fde = sframe_fde_alloc (); 1342 /* Initialize the translation context with information anew. */ 1343 sframe_xlate_ctx_init (xlate_ctx); 1344 1345 /* Process and link SFrame FDEs if no error. Also skip adding an SFrame 1346 FDE if it does not contain any SFrame FREs. There is little use of an 1347 SFrame FDE if there is no stack tracing information for the 1348 function. */ 1349 int err = sframe_do_fde (xlate_ctx, dw_fde); 1350 if (err || xlate_ctx->num_xlate_fres == 0) 1351 { 1352 sframe_xlate_ctx_cleanup (xlate_ctx); 1353 sframe_fde_free (sframe_fde); 1354 } 1355 else 1356 { 1357 /* All done. Transfer the state from the SFrame translation 1358 context to the SFrame FDE. */ 1359 sframe_xlate_ctx_finalize (xlate_ctx, sframe_fde); 1360 sframe_fde_link (sframe_fde); 1361 } 1362 } 1363} 1364 1365void 1366output_sframe (segT sframe_seg) 1367{ 1368 (void) sframe_seg; 1369 1370 /* Setup the version specific access functions. */ 1371 sframe_set_version (SFRAME_VERSION_2); 1372 1373 /* Process all fdes and create SFrame stack trace information. */ 1374 create_sframe_all (); 1375 1376 output_sframe_internal (); 1377} 1378 1379#else /* support_sframe_p */ 1380 1381void 1382output_sframe (segT sframe_seg ATTRIBUTE_UNUSED) 1383{ 1384} 1385 1386#endif /* support_sframe_p */ 1387