1/* scfi.c - Support for synthesizing DWARF CFI for hand-written asm. 2 Copyright (C) 2023 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 "scfi.h" 23#include "subsegs.h" 24#include "scfidw2gen.h" 25#include "dw2gencfi.h" 26 27#if defined (TARGET_USE_SCFI) && defined (TARGET_USE_GINSN) 28 29/* Beyond the target defined number of registers to be tracked 30 (SCFI_MAX_REG_ID), keep the next register ID, in sequence, for REG_CFA. */ 31#define REG_CFA (SCFI_MAX_REG_ID+1) 32/* Define the total number of registers being tracked. 33 Used as index into an array of cfi_reglocS. Note that a ginsn may carry a 34 register number greater than MAX_NUM_SCFI_REGS, e.g., for the ginsns 35 corresponding to push fs/gs in AMD64. */ 36#define MAX_NUM_SCFI_REGS (REG_CFA+1) 37 38#define REG_INVALID ((unsigned int)-1) 39 40enum cfi_reglocstate 41{ 42 CFI_UNDEFINED, 43 CFI_IN_REG, 44 CFI_ON_STACK 45}; 46 47/* Location at which CFI register is saved. 48 49 A CFI register (callee-saved registers, RA/LR) are always an offset from 50 the CFA. REG_CFA itself, however, may have REG_SP or REG_FP as base 51 register. Hence, keep the base reg ID and offset per tracked register. */ 52 53struct cfi_regloc 54{ 55 /* Base reg ID (DWARF register number). */ 56 unsigned int base; 57 /* Location as offset from the CFA. */ 58 offsetT offset; 59 /* Current state of the CFI register. */ 60 enum cfi_reglocstate state; 61}; 62 63typedef struct cfi_regloc cfi_reglocS; 64 65struct scfi_op_data 66{ 67 const char *name; 68}; 69 70typedef struct scfi_op_data scfi_op_dataS; 71 72/* SCFI operation. 73 74 An SCFI operation represents a single atomic change to the SCFI state. 75 This can also be understood as an abstraction for what eventually gets 76 emitted as a DWARF CFI operation. */ 77 78struct scfi_op 79{ 80 /* An SCFI op updates the state of either the CFA or other tracked 81 (callee-saved, REG_SP etc) registers. 'reg' is in the DWARF register 82 number space and must be strictly less than MAX_NUM_SCFI_REGS. */ 83 unsigned int reg; 84 /* Location of the reg. */ 85 cfi_reglocS loc; 86 /* DWARF CFI opcode. */ 87 uint32_t dw2cfi_op; 88 /* Some SCFI ops, e.g., for CFI_label, may need to carry additional data. */ 89 scfi_op_dataS *op_data; 90 /* A linked list. */ 91 struct scfi_op *next; 92}; 93 94/* SCFI State - accumulated unwind information at a PC. 95 96 SCFI state is the accumulated unwind information encompassing: 97 - REG_SP, REG_FP, 98 - RA, and 99 - all callee-saved registers. 100 101 Note that SCFI_MAX_REG_ID is target/ABI dependent and is provided by the 102 backends. The backend must also identify the DWARF register numbers for 103 the REG_SP, and REG_FP registers. */ 104 105struct scfi_state 106{ 107 cfi_reglocS regs[MAX_NUM_SCFI_REGS]; 108 cfi_reglocS scratch[MAX_NUM_SCFI_REGS]; 109 /* Current stack size. */ 110 offsetT stack_size; 111 /* Whether the stack size is known. 112 Stack size may become untraceable depending on the specific stack 113 manipulation machine instruction, e.g., rsp = rsp op reg instruction 114 makes the stack size untraceable. */ 115 bool traceable_p; 116}; 117 118/* Initialize a new SCFI op. */ 119 120static scfi_opS * 121init_scfi_op (void) 122{ 123 scfi_opS *op = XCNEW (scfi_opS); 124 125 return op; 126} 127 128/* Free the SCFI ops, given the HEAD of the list. */ 129 130void 131scfi_ops_cleanup (scfi_opS **head) 132{ 133 scfi_opS *op; 134 scfi_opS *next; 135 136 if (!head || !*head) 137 return; 138 139 op = *head; 140 next = op->next; 141 142 while (op) 143 { 144 free (op); 145 op = next; 146 next = op ? op->next : NULL; 147 } 148} 149 150/* Compare two SCFI states. */ 151 152static int 153cmp_scfi_state (scfi_stateS *state1, scfi_stateS *state2) 154{ 155 int ret; 156 157 if (!state1 || !state2) 158 ret = 1; 159 160 /* Skip comparing the scratch[] value of registers. The user visible 161 unwind information is derived from the regs[] from the SCFI state. */ 162 ret = memcmp (state1->regs, state2->regs, 163 sizeof (cfi_reglocS) * MAX_NUM_SCFI_REGS); 164 165 /* For user functions which perform dynamic stack allocation, after switching 166 t REG_FP based CFA tracking, it is perfectly possible to have stack usage 167 in some control flows. However, double-checking that all control flows 168 have the same idea of CFA tracking before this wont hurt. */ 169 gas_assert (state1->regs[REG_CFA].base == state2->regs[REG_CFA].base); 170 if (state1->regs[REG_CFA].base == REG_SP) 171 ret |= state1->stack_size != state2->stack_size; 172 173 ret |= state1->traceable_p != state2->traceable_p; 174 175 return ret; 176} 177 178#if 0 179static void 180scfi_state_update_reg (scfi_stateS *state, uint32_t dst, uint32_t base, 181 int32_t offset) 182{ 183 if (dst >= MAX_NUM_SCFI_REGS) 184 return; 185 186 state->regs[dst].base = base; 187 state->regs[dst].offset = offset; 188} 189#endif 190 191/* Update the SCFI state of REG as available on execution stack at OFFSET 192 from REG_CFA (BASE). 193 194 Note that BASE must be REG_CFA, because any other base (REG_SP, REG_FP) 195 is by definition transitory in the function. */ 196 197static void 198scfi_state_save_reg (scfi_stateS *state, unsigned int reg, unsigned int base, 199 offsetT offset) 200{ 201 if (reg >= MAX_NUM_SCFI_REGS) 202 return; 203 204 gas_assert (base == REG_CFA); 205 206 state->regs[reg].base = base; 207 state->regs[reg].offset = offset; 208 state->regs[reg].state = CFI_ON_STACK; 209} 210 211static void 212scfi_state_restore_reg (scfi_stateS *state, unsigned int reg) 213{ 214 if (reg >= MAX_NUM_SCFI_REGS) 215 return; 216 217 /* Sanity check. See Rule 4. */ 218 gas_assert (state->regs[reg].state == CFI_ON_STACK); 219 gas_assert (state->regs[reg].base == REG_CFA); 220 221 state->regs[reg].base = reg; 222 state->regs[reg].offset = 0; 223 /* PS: the register may still be on stack much after the restore, but the 224 SCFI state keeps the state as 'in register'. */ 225 state->regs[reg].state = CFI_IN_REG; 226} 227 228/* Identify if the given GAS instruction GINSN saves a register 229 (of interest) on stack. */ 230 231static bool 232ginsn_scfi_save_reg_p (ginsnS *ginsn, scfi_stateS *state) 233{ 234 bool save_reg_p = false; 235 struct ginsn_src *src; 236 struct ginsn_dst *dst; 237 238 src = ginsn_get_src1 (ginsn); 239 dst = ginsn_get_dst (ginsn); 240 241 /* The first save to stack of callee-saved register is deemed as 242 register save. */ 243 if (!ginsn_track_reg_p (ginsn_get_src_reg (src), GINSN_GEN_SCFI) 244 || state->regs[ginsn_get_src_reg (src)].state == CFI_ON_STACK) 245 return save_reg_p; 246 247 /* A register save insn may be an indirect mov. */ 248 if (ginsn->type == GINSN_TYPE_MOV 249 && ginsn_get_dst_type (dst) == GINSN_DST_INDIRECT 250 && (ginsn_get_dst_reg (dst) == REG_SP 251 || (ginsn_get_dst_reg (dst) == REG_FP 252 && state->regs[REG_CFA].base == REG_FP))) 253 save_reg_p = true; 254 /* or an explicit store to stack. */ 255 else if (ginsn->type == GINSN_TYPE_STORE 256 && ginsn_get_dst_type (dst) == GINSN_DST_INDIRECT 257 && ginsn_get_dst_reg (dst) == REG_SP) 258 save_reg_p = true; 259 260 return save_reg_p; 261} 262 263/* Identify if the given GAS instruction GINSN restores a register 264 (of interest) on stack. */ 265 266static bool 267ginsn_scfi_restore_reg_p (ginsnS *ginsn, scfi_stateS *state) 268{ 269 bool restore_reg_p = false; 270 struct ginsn_dst *dst; 271 struct ginsn_src *src1; 272 273 dst = ginsn_get_dst (ginsn); 274 src1 = ginsn_get_src1 (ginsn); 275 276 if (!ginsn_track_reg_p (ginsn_get_dst_reg (dst), GINSN_GEN_SCFI)) 277 return restore_reg_p; 278 279 /* A register restore insn may be an indirect mov... */ 280 if (ginsn->type == GINSN_TYPE_MOV 281 && ginsn_get_src_type (src1) == GINSN_SRC_INDIRECT 282 && (ginsn_get_src_reg (src1) == REG_SP 283 || (ginsn_get_src_reg (src1) == REG_FP 284 && state->regs[REG_CFA].base == REG_FP))) 285 restore_reg_p = true; 286 /* ...or an explicit load from stack. */ 287 else if (ginsn->type == GINSN_TYPE_LOAD 288 && ginsn_get_src_type (src1) == GINSN_SRC_INDIRECT 289 && ginsn_get_src_reg (src1) == REG_SP) 290 restore_reg_p = true; 291 292 return restore_reg_p; 293} 294 295/* Append the SCFI operation OP to the list of SCFI operations in the 296 given GINSN. */ 297 298static int 299ginsn_append_scfi_op (ginsnS *ginsn, scfi_opS *op) 300{ 301 scfi_opS *sop; 302 303 if (!ginsn || !op) 304 return 1; 305 306 if (!ginsn->scfi_ops) 307 { 308 ginsn->scfi_ops = XCNEW (scfi_opS *); 309 *ginsn->scfi_ops = op; 310 } 311 else 312 { 313 /* Add to tail. Most ginsns have a single SCFI operation, 314 so this traversal for every insertion is acceptable for now. */ 315 sop = *ginsn->scfi_ops; 316 while (sop->next) 317 sop = sop->next; 318 319 sop->next = op; 320 } 321 ginsn->num_scfi_ops++; 322 323 return 0; 324} 325 326static void 327scfi_op_add_def_cfa_reg (scfi_stateS *state, ginsnS *ginsn, unsigned int reg) 328{ 329 scfi_opS *op = NULL; 330 331 state->regs[REG_CFA].base = reg; 332 333 op = init_scfi_op (); 334 335 op->dw2cfi_op = DW_CFA_def_cfa_register; 336 op->reg = REG_CFA; 337 op->loc = state->regs[REG_CFA]; 338 339 ginsn_append_scfi_op (ginsn, op); 340} 341 342static void 343scfi_op_add_cfa_offset_inc (scfi_stateS *state, ginsnS *ginsn, offsetT num) 344{ 345 scfi_opS *op = NULL; 346 347 state->regs[REG_CFA].offset -= num; 348 349 op = init_scfi_op (); 350 351 op->dw2cfi_op = DW_CFA_def_cfa_offset; 352 op->reg = REG_CFA; 353 op->loc = state->regs[REG_CFA]; 354 355 ginsn_append_scfi_op (ginsn, op); 356} 357 358static void 359scfi_op_add_cfa_offset_dec (scfi_stateS *state, ginsnS *ginsn, offsetT num) 360{ 361 scfi_opS *op = NULL; 362 363 state->regs[REG_CFA].offset += num; 364 365 op = init_scfi_op (); 366 367 op->dw2cfi_op = DW_CFA_def_cfa_offset; 368 op->reg = REG_CFA; 369 op->loc = state->regs[REG_CFA]; 370 371 ginsn_append_scfi_op (ginsn, op); 372} 373 374static void 375scfi_op_add_def_cfa (scfi_stateS *state, ginsnS *ginsn, unsigned int reg, 376 offsetT num) 377{ 378 scfi_opS *op = NULL; 379 380 state->regs[REG_CFA].base = reg; 381 state->regs[REG_CFA].offset = num; 382 383 op = init_scfi_op (); 384 385 op->dw2cfi_op = DW_CFA_def_cfa; 386 op->reg = REG_CFA; 387 op->loc = state->regs[REG_CFA]; 388 389 ginsn_append_scfi_op (ginsn, op); 390} 391 392static void 393scfi_op_add_cfi_offset (scfi_stateS *state, ginsnS *ginsn, unsigned int reg) 394{ 395 scfi_opS *op = NULL; 396 397 op = init_scfi_op (); 398 399 op->dw2cfi_op = DW_CFA_offset; 400 op->reg = reg; 401 op->loc = state->regs[reg]; 402 403 ginsn_append_scfi_op (ginsn, op); 404} 405 406static void 407scfi_op_add_cfa_restore (ginsnS *ginsn, unsigned int reg) 408{ 409 scfi_opS *op = NULL; 410 411 op = init_scfi_op (); 412 413 op->dw2cfi_op = DW_CFA_restore; 414 op->reg = reg; 415 op->loc.base = REG_INVALID; 416 op->loc.offset = 0; 417 418 ginsn_append_scfi_op (ginsn, op); 419} 420 421static void 422scfi_op_add_cfi_remember_state (ginsnS *ginsn) 423{ 424 scfi_opS *op = NULL; 425 426 op = init_scfi_op (); 427 428 op->dw2cfi_op = DW_CFA_remember_state; 429 430 ginsn_append_scfi_op (ginsn, op); 431} 432 433static void 434scfi_op_add_cfi_restore_state (ginsnS *ginsn) 435{ 436 scfi_opS *op = NULL; 437 438 op = init_scfi_op (); 439 440 op->dw2cfi_op = DW_CFA_restore_state; 441 442 /* FIXME - add to the beginning of the scfi_ops. */ 443 ginsn_append_scfi_op (ginsn, op); 444} 445 446void 447scfi_op_add_cfi_label (ginsnS *ginsn, const char *name) 448{ 449 scfi_opS *op = NULL; 450 451 op = init_scfi_op (); 452 op->dw2cfi_op = CFI_label; 453 op->op_data = XCNEW (scfi_op_dataS); 454 op->op_data->name = name; 455 456 ginsn_append_scfi_op (ginsn, op); 457} 458 459void 460scfi_op_add_signal_frame (ginsnS *ginsn) 461{ 462 scfi_opS *op = NULL; 463 464 op = init_scfi_op (); 465 op->dw2cfi_op = CFI_signal_frame; 466 467 ginsn_append_scfi_op (ginsn, op); 468} 469 470static int 471verify_heuristic_traceable_reg_fp (ginsnS *ginsn, scfi_stateS *state) 472{ 473 /* The function uses this variable to issue error to user right away. */ 474 int fp_traceable_p = 0; 475 struct ginsn_dst *dst; 476 struct ginsn_src *src1; 477 struct ginsn_src *src2; 478 479 src1 = ginsn_get_src1 (ginsn); 480 src2 = ginsn_get_src2 (ginsn); 481 dst = ginsn_get_dst (ginsn); 482 483 /* Stack manipulation can be done in a variety of ways. A program may 484 allocate stack statically or may perform dynamic stack allocation in 485 the prologue. 486 487 The SCFI machinery in GAS is based on some heuristics: 488 489 - Rule 3 If the base register for CFA tracking is REG_FP, the program 490 must not clobber REG_FP, unless it is for switch to REG_SP based CFA 491 tracking (via say, a pop %rbp in X86). */ 492 493 /* Check all applicable instructions with dest REG_FP, when the CFA base 494 register is REG_FP. */ 495 if (state->regs[REG_CFA].base == REG_FP && ginsn_get_dst_reg (dst) == REG_FP) 496 { 497 /* Excuse the add/sub with imm usage: They are OK. */ 498 if ((ginsn->type == GINSN_TYPE_ADD || ginsn->type == GINSN_TYPE_SUB) 499 && ginsn_get_src_reg (src1) == REG_FP 500 && ginsn_get_src_type (src2) == GINSN_SRC_IMM) 501 fp_traceable_p = 0; 502 /* REG_FP restore is OK too. */ 503 else if (ginsn->type == GINSN_TYPE_LOAD) 504 fp_traceable_p = 0; 505 /* mov's to memory with REG_FP base do not make REG_FP untraceable. */ 506 else if (ginsn_get_dst_type (dst) == GINSN_DST_INDIRECT 507 && (ginsn->type == GINSN_TYPE_MOV 508 || ginsn->type == GINSN_TYPE_STORE)) 509 fp_traceable_p = 0; 510 /* Manipulations of the values possibly on stack are OK too. */ 511 else if ((ginsn->type == GINSN_TYPE_ADD || ginsn->type == GINSN_TYPE_SUB 512 || ginsn->type == GINSN_TYPE_AND) 513 && ginsn_get_dst_type (dst) == GINSN_DST_INDIRECT) 514 fp_traceable_p = 0; 515 /* All other ginsns with REG_FP as destination make REG_FP not 516 traceable. */ 517 else 518 fp_traceable_p = 1; 519 } 520 521 if (fp_traceable_p) 522 as_bad_where (ginsn->file, ginsn->line, 523 _("SCFI: usage of REG_FP as scratch not supported")); 524 525 return fp_traceable_p; 526} 527 528static int 529verify_heuristic_traceable_stack_manipulation (ginsnS *ginsn, 530 scfi_stateS *state) 531{ 532 /* The function uses this variable to issue error to user right away. */ 533 int sp_untraceable_p = 0; 534 bool possibly_untraceable = false; 535 struct ginsn_dst *dst; 536 struct ginsn_src *src1; 537 struct ginsn_src *src2; 538 539 src1 = ginsn_get_src1 (ginsn); 540 src2 = ginsn_get_src2 (ginsn); 541 dst = ginsn_get_dst (ginsn); 542 543 /* Stack manipulation can be done in a variety of ways. A program may 544 allocate stack statically in prologue or may need to do dynamic stack 545 allocation. 546 547 The SCFI machinery in GAS is based on some heuristics: 548 549 - Rule 1 The base register for CFA tracking may be either REG_SP or 550 REG_FP. 551 552 - Rule 2 If the base register for CFA tracking is REG_SP, the precise 553 amount of stack usage (and hence, the value of rsp) must be known at 554 all times. */ 555 556 if (ginsn->type == GINSN_TYPE_MOV 557 && ginsn_get_dst_type (dst) == GINSN_DST_REG 558 && ginsn_get_dst_reg (dst) == REG_SP 559 && ginsn_get_src_type (src1) == GINSN_SRC_REG 560 /* Exclude mov %rbp, %rsp from this check. */ 561 && ginsn_get_src_reg (src1) != REG_FP) 562 { 563 /* mov %reg, %rsp. */ 564 /* A previous mov %rsp, %reg must have been seen earlier for this to be 565 an OK for stack manipulation. */ 566 if (state->scratch[ginsn_get_src_reg (src1)].base != REG_CFA 567 || state->scratch[ginsn_get_src_reg (src1)].state != CFI_IN_REG) 568 { 569 possibly_untraceable = true; 570 } 571 } 572 /* Check add/sub/and insn usage when CFA base register is REG_SP. 573 Any stack size manipulation, including stack realignment is not allowed 574 if CFA base register is REG_SP. */ 575 else if (ginsn_get_dst_type (dst) == GINSN_DST_REG 576 && ginsn_get_dst_reg (dst) == REG_SP 577 && (((ginsn->type == GINSN_TYPE_ADD || ginsn->type == GINSN_TYPE_SUB) 578 && ginsn_get_src_type (src2) != GINSN_SRC_IMM) 579 || ginsn->type == GINSN_TYPE_AND 580 || ginsn->type == GINSN_TYPE_OTHER)) 581 possibly_untraceable = true; 582 /* If a register save operation is seen when REG_SP is untraceable, 583 CFI cannot be synthesized for register saves, hence bail out. */ 584 else if (ginsn_scfi_save_reg_p (ginsn, state) && !state->traceable_p) 585 { 586 sp_untraceable_p = 1; 587 /* If, however, the register save is an REG_FP-based, indirect mov 588 like: mov reg, disp(%rbp) and CFA base register is REG_BP, 589 untraceable REG_SP is not a problem. */ 590 if (ginsn->type == GINSN_TYPE_MOV 591 && ginsn_get_dst_type (dst) == GINSN_DST_INDIRECT 592 && (ginsn_get_dst_reg (dst) == REG_FP 593 && state->regs[REG_CFA].base == REG_FP)) 594 sp_untraceable_p = 0; 595 } 596 else if (ginsn_scfi_restore_reg_p (ginsn, state) && !state->traceable_p) 597 { 598 if (ginsn->type == GINSN_TYPE_MOV 599 && ginsn_get_dst_type (dst) == GINSN_DST_INDIRECT 600 && (ginsn_get_src_reg (src1) == REG_SP 601 || (ginsn_get_src_reg (src1) == REG_FP 602 && state->regs[REG_CFA].base != REG_FP))) 603 sp_untraceable_p = 1; 604 } 605 606 if (possibly_untraceable) 607 { 608 /* See Rule 2. For SP-based CFA, this makes CFA tracking not possible. 609 Propagate now to caller. */ 610 if (state->regs[REG_CFA].base == REG_SP) 611 sp_untraceable_p = 1; 612 else if (state->traceable_p) 613 { 614 /* An extension of Rule 2. 615 For FP-based CFA, this may be a problem *if* certain specific 616 changes to the SCFI state are seen beyond this point, e.g., 617 register save / restore from stack. */ 618 gas_assert (state->regs[REG_CFA].base == REG_FP); 619 /* Simply make a note in the SCFI state object for now and 620 continue. Indicate an error when register save / restore 621 for callee-saved registers is seen. */ 622 sp_untraceable_p = 0; 623 state->traceable_p = false; 624 } 625 } 626 627 if (sp_untraceable_p) 628 as_bad_where (ginsn->file, ginsn->line, 629 _("SCFI: unsupported stack manipulation pattern")); 630 631 return sp_untraceable_p; 632} 633 634static int 635verify_heuristic_symmetrical_restore_reg (scfi_stateS *state, ginsnS* ginsn) 636{ 637 int sym_restore = true; 638 offsetT expected_offset = 0; 639 struct ginsn_src *src1; 640 struct ginsn_dst *dst; 641 unsigned int reg; 642 643 /* Rule 4: Save and Restore of callee-saved registers must be symmetrical. 644 It is expected that value of the saved register is restored correctly. 645 E.g., 646 push reg1 647 push reg2 648 ... 649 body of func which uses reg1 , reg2 as scratch, 650 and may be even spills them to stack. 651 ... 652 pop reg2 653 pop reg1 654 It is difficult to verify the Rule 4 in all cases. For the SCFI machinery, 655 it is difficult to separate prologue-epilogue from the body of the function 656 657 Hence, the SCFI machinery at this time, should only warn on an asymetrical 658 restore. */ 659 src1 = ginsn_get_src1 (ginsn); 660 dst = ginsn_get_dst (ginsn); 661 reg = ginsn_get_dst_reg (dst); 662 663 /* For non callee-saved registers, calling the API is meaningless. */ 664 if (!ginsn_track_reg_p (ginsn_get_dst_reg (dst), GINSN_GEN_SCFI)) 665 return sym_restore; 666 667 /* The register must have been saved on stack, for sure. */ 668 gas_assert (state->regs[reg].state == CFI_ON_STACK); 669 gas_assert (state->regs[reg].base == REG_CFA); 670 671 if ((ginsn->type == GINSN_TYPE_MOV 672 || ginsn->type == GINSN_TYPE_LOAD) 673 && ginsn_get_src_type (src1) == GINSN_SRC_INDIRECT 674 && (ginsn_get_src_reg (src1) == REG_SP 675 || (ginsn_get_src_reg (src1) == REG_FP 676 && state->regs[REG_CFA].base == REG_FP))) 677 { 678 /* mov disp(%rsp), reg. */ 679 /* mov disp(%rbp), reg. */ 680 expected_offset = (((ginsn_get_src_reg (src1) == REG_SP) 681 ? -state->stack_size 682 : state->regs[REG_FP].offset) 683 + ginsn_get_src_disp (src1)); 684 } 685 686 sym_restore = (expected_offset == state->regs[reg].offset); 687 688 return sym_restore; 689} 690 691/* Perform symbolic execution of the GINSN and update its list of scfi_ops. 692 scfi_ops are later used to directly generate the DWARF CFI directives. 693 Also update the SCFI state object STATE for the caller. */ 694 695static int 696gen_scfi_ops (ginsnS *ginsn, scfi_stateS *state) 697{ 698 int ret = 0; 699 offsetT offset; 700 struct ginsn_src *src1; 701 struct ginsn_src *src2; 702 struct ginsn_dst *dst; 703 704 if (!ginsn || !state) 705 ret = 1; 706 707 /* For the first ginsn (of type GINSN_TYPE_SYMBOL) in the gbb, generate 708 the SCFI op with DW_CFA_def_cfa. Note that the register and offset are 709 target-specific. */ 710 if (GINSN_F_FUNC_BEGIN_P (ginsn)) 711 { 712 scfi_op_add_def_cfa (state, ginsn, REG_SP, SCFI_INIT_CFA_OFFSET); 713 state->stack_size += SCFI_INIT_CFA_OFFSET; 714 return ret; 715 } 716 717 src1 = ginsn_get_src1 (ginsn); 718 src2 = ginsn_get_src2 (ginsn); 719 dst = ginsn_get_dst (ginsn); 720 721 ret = verify_heuristic_traceable_stack_manipulation (ginsn, state); 722 if (ret) 723 return ret; 724 725 ret = verify_heuristic_traceable_reg_fp (ginsn, state); 726 if (ret) 727 return ret; 728 729 switch (ginsn->dst.type) 730 { 731 case GINSN_DST_REG: 732 switch (ginsn->type) 733 { 734 case GINSN_TYPE_MOV: 735 if (ginsn_get_src_type (src1) == GINSN_SRC_REG 736 && ginsn_get_src_reg (src1) == REG_SP 737 && ginsn_get_dst_reg (dst) == REG_FP 738 && state->regs[REG_CFA].base == REG_SP) 739 { 740 /* mov %rsp, %rbp. */ 741 scfi_op_add_def_cfa_reg (state, ginsn, ginsn_get_dst_reg (dst)); 742 } 743 else if (ginsn_get_src_type (src1) == GINSN_SRC_REG 744 && ginsn_get_src_reg (src1) == REG_FP 745 && ginsn_get_dst_reg (dst) == REG_SP 746 && state->regs[REG_CFA].base == REG_FP) 747 { 748 /* mov %rbp, %rsp. */ 749 state->stack_size = -state->regs[REG_FP].offset; 750 scfi_op_add_def_cfa_reg (state, ginsn, ginsn_get_dst_reg (dst)); 751 state->traceable_p = true; 752 } 753 else if (ginsn_get_src_type (src1) == GINSN_SRC_INDIRECT 754 && (ginsn_get_src_reg (src1) == REG_SP 755 || ginsn_get_src_reg (src1) == REG_FP) 756 && ginsn_track_reg_p (ginsn_get_dst_reg (dst), GINSN_GEN_SCFI)) 757 { 758 /* mov disp(%rsp), reg. */ 759 /* mov disp(%rbp), reg. */ 760 if (verify_heuristic_symmetrical_restore_reg (state, ginsn)) 761 { 762 scfi_state_restore_reg (state, ginsn_get_dst_reg (dst)); 763 scfi_op_add_cfa_restore (ginsn, ginsn_get_dst_reg (dst)); 764 } 765 else 766 as_warn_where (ginsn->file, ginsn->line, 767 _("SCFI: asymetrical register restore")); 768 } 769 else if (ginsn_get_src_type (src1) == GINSN_SRC_REG 770 && ginsn_get_dst_type (dst) == GINSN_DST_REG 771 && ginsn_get_src_reg (src1) == REG_SP) 772 { 773 /* mov %rsp, %reg. */ 774 /* The value of rsp is taken directly from state->stack_size. 775 IMP: The workflow in gen_scfi_ops must keep it updated. 776 PS: Not taking the value from state->scratch[REG_SP] is 777 intentional. */ 778 state->scratch[ginsn_get_dst_reg (dst)].base = REG_CFA; 779 state->scratch[ginsn_get_dst_reg (dst)].offset = -state->stack_size; 780 state->scratch[ginsn_get_dst_reg (dst)].state = CFI_IN_REG; 781 } 782 else if (ginsn_get_src_type (src1) == GINSN_SRC_REG 783 && ginsn_get_dst_type (dst) == GINSN_DST_REG 784 && ginsn_get_dst_reg (dst) == REG_SP) 785 { 786 /* mov %reg, %rsp. */ 787 /* Keep the value of REG_SP updated. */ 788 if (state->scratch[ginsn_get_src_reg (src1)].state == CFI_IN_REG) 789 { 790 state->stack_size = -state->scratch[ginsn_get_src_reg (src1)].offset; 791 state->traceable_p = true; 792 } 793# if 0 794 scfi_state_update_reg (state, ginsn_get_dst_reg (dst), 795 state->scratch[ginsn_get_src_reg (src1)].base, 796 state->scratch[ginsn_get_src_reg (src1)].offset); 797#endif 798 799 } 800 break; 801 case GINSN_TYPE_SUB: 802 if (ginsn_get_src_reg (src1) == REG_SP 803 && ginsn_get_dst_reg (dst) == REG_SP) 804 { 805 /* Stack inc/dec offset, when generated due to stack push and pop is 806 target-specific. Use the value encoded in the ginsn. */ 807 state->stack_size += ginsn_get_src_imm (src2); 808 if (state->regs[REG_CFA].base == REG_SP) 809 { 810 /* push reg. */ 811 scfi_op_add_cfa_offset_dec (state, ginsn, ginsn_get_src_imm (src2)); 812 } 813 } 814 break; 815 case GINSN_TYPE_ADD: 816 if (ginsn_get_src_reg (src1) == REG_SP 817 && ginsn_get_dst_reg (dst) == REG_SP) 818 { 819 /* Stack inc/dec offset is target-specific. Use the value 820 encoded in the ginsn. */ 821 state->stack_size -= ginsn_get_src_imm (src2); 822 /* pop %reg affects CFA offset only if CFA is currently 823 stack-pointer based. */ 824 if (state->regs[REG_CFA].base == REG_SP) 825 { 826 scfi_op_add_cfa_offset_inc (state, ginsn, ginsn_get_src_imm (src2)); 827 } 828 } 829 else if (ginsn_get_src_reg (src1) == REG_FP 830 && ginsn_get_dst_reg (dst) == REG_SP 831 && state->regs[REG_CFA].base == REG_FP) 832 { 833 /* FIXME - what is this for ? */ 834 state->stack_size = 0 - (state->regs[REG_FP].offset + ginsn_get_src_imm (src2)); 835 } 836 break; 837 case GINSN_TYPE_LOAD: 838 /* If this is a load from stack. */ 839 if (ginsn_get_src_type (src1) == GINSN_SRC_INDIRECT 840 && (ginsn_get_src_reg (src1) == REG_SP 841 || (ginsn_get_src_reg (src1) == REG_FP 842 && state->regs[REG_CFA].base == REG_FP))) 843 { 844 /* pop %rbp when CFA tracking is REG_FP based. */ 845 if (ginsn_get_dst_reg (dst) == REG_FP 846 && state->regs[REG_CFA].base == REG_FP) 847 { 848 scfi_op_add_def_cfa_reg (state, ginsn, REG_SP); 849 if (state->regs[REG_CFA].offset != state->stack_size) 850 scfi_op_add_cfa_offset_inc (state, ginsn, 851 (state->regs[REG_CFA].offset - state->stack_size)); 852 } 853 if (ginsn_track_reg_p (ginsn_get_dst_reg (dst), GINSN_GEN_SCFI)) 854 { 855 if (verify_heuristic_symmetrical_restore_reg (state, ginsn)) 856 { 857 scfi_state_restore_reg (state, ginsn_get_dst_reg (dst)); 858 scfi_op_add_cfa_restore (ginsn, ginsn_get_dst_reg (dst)); 859 } 860 else 861 as_warn_where (ginsn->file, ginsn->line, 862 _("SCFI: asymetrical register restore")); 863 } 864 } 865 break; 866 default: 867 break; 868 } 869 break; 870 871 case GINSN_DST_INDIRECT: 872 /* Some operations with an indirect access to memory (or even to stack) 873 may still be uninteresting for SCFI purpose (e.g, addl %edx, -32(%rsp) 874 in x86). In case of x86_64, these can neither be a register 875 save / unsave, nor can alter the stack size. 876 PS: This condition may need to be revisited for other arches. */ 877 if (ginsn->type == GINSN_TYPE_ADD || ginsn->type == GINSN_TYPE_SUB 878 || ginsn->type == GINSN_TYPE_AND) 879 break; 880 gas_assert (ginsn->type == GINSN_TYPE_MOV 881 || ginsn->type == GINSN_TYPE_STORE 882 || ginsn->type == GINSN_TYPE_LOAD); 883 /* mov reg, disp(%rbp) */ 884 /* mov reg, disp(%rsp) */ 885 if (ginsn_scfi_save_reg_p (ginsn, state)) 886 { 887 if (ginsn_get_dst_reg (dst) == REG_SP) 888 { 889 /* mov reg, disp(%rsp) */ 890 offset = 0 - state->stack_size + ginsn_get_dst_disp (dst); 891 scfi_state_save_reg (state, ginsn_get_src_reg (src1), REG_CFA, offset); 892 scfi_op_add_cfi_offset (state, ginsn, ginsn_get_src_reg (src1)); 893 } 894 else if (ginsn_get_dst_reg (dst) == REG_FP) 895 { 896 gas_assert (state->regs[REG_CFA].base == REG_FP); 897 /* mov reg, disp(%rbp) */ 898 offset = 0 - state->regs[REG_CFA].offset + ginsn_get_dst_disp (dst); 899 scfi_state_save_reg (state, ginsn_get_src_reg (src1), REG_CFA, offset); 900 scfi_op_add_cfi_offset (state, ginsn, ginsn_get_src_reg (src1)); 901 } 902 } 903 break; 904 905 default: 906 /* Skip GINSN_DST_UNKNOWN and GINSN_DST_MEM as they are uninteresting 907 currently for SCFI. */ 908 break; 909 } 910 911 return ret; 912} 913 914/* Recursively perform forward flow of the (unwind information) SCFI state 915 starting at basic block GBB. 916 917 The forward flow process propagates the SCFI state at exit of a basic block 918 to the successor basic block. 919 920 Returns error code, if any. */ 921 922static int 923forward_flow_scfi_state (gcfgS *gcfg, gbbS *gbb, scfi_stateS *state) 924{ 925 ginsnS *ginsn; 926 gbbS *prev_bb; 927 gedgeS *gedge = NULL; 928 int ret = 0; 929 930 if (gbb->visited) 931 { 932 /* Check that the SCFI state is the same as previous. */ 933 ret = cmp_scfi_state (state, gbb->entry_state); 934 if (ret) 935 as_bad (_("SCFI: Bad CFI propagation perhaps")); 936 return ret; 937 } 938 939 gbb->visited = true; 940 941 gbb->entry_state = XCNEW (scfi_stateS); 942 memcpy (gbb->entry_state, state, sizeof (scfi_stateS)); 943 944 /* Perform symbolic execution of each ginsn in the gbb and update the 945 scfi_ops list of each ginsn (and also update the STATE object). */ 946 bb_for_each_insn(gbb, ginsn) 947 { 948 ret = gen_scfi_ops (ginsn, state); 949 if (ret) 950 goto fail; 951 } 952 953 gbb->exit_state = XCNEW (scfi_stateS); 954 memcpy (gbb->exit_state, state, sizeof (scfi_stateS)); 955 956 /* Forward flow the SCFI state. Currently, we process the next basic block 957 in DFS order. But any forward traversal order should be fine. */ 958 prev_bb = gbb; 959 if (gbb->num_out_gedges) 960 { 961 bb_for_each_edge(gbb, gedge) 962 { 963 gbb = gedge->dst_bb; 964 if (gbb->visited) 965 { 966 ret = cmp_scfi_state (gbb->entry_state, state); 967 if (ret) 968 goto fail; 969 } 970 971 if (!gedge->visited) 972 { 973 gedge->visited = true; 974 975 /* Entry SCFI state for the destination bb of the edge is the 976 same as the exit SCFI state of the source bb of the edge. */ 977 memcpy (state, prev_bb->exit_state, sizeof (scfi_stateS)); 978 ret = forward_flow_scfi_state (gcfg, gbb, state); 979 if (ret) 980 goto fail; 981 } 982 } 983 } 984 985 return 0; 986 987fail: 988 989 if (gedge) 990 gedge->visited = true; 991 return 1; 992} 993 994static int 995backward_flow_scfi_state (const symbolS *func ATTRIBUTE_UNUSED, gcfgS *gcfg) 996{ 997 gbbS **prog_order_bbs; 998 gbbS **restore_bbs; 999 gbbS *current_bb; 1000 gbbS *prev_bb; 1001 gbbS *dst_bb; 1002 ginsnS *ginsn; 1003 gedgeS *gedge = NULL; 1004 1005 int ret = 0; 1006 uint64_t i, j; 1007 1008 /* Basic blocks in reverse program order. */ 1009 prog_order_bbs = XCNEWVEC (gbbS *, gcfg->num_gbbs); 1010 /* Basic blocks for which CFI remember op needs to be generated. */ 1011 restore_bbs = XCNEWVEC (gbbS *, gcfg->num_gbbs); 1012 1013 gcfg_get_bbs_in_prog_order (gcfg, prog_order_bbs); 1014 1015 i = gcfg->num_gbbs - 1; 1016 /* Traverse in reverse program order. */ 1017 while (i > 0) 1018 { 1019 current_bb = prog_order_bbs[i]; 1020 prev_bb = prog_order_bbs[i-1]; 1021 if (cmp_scfi_state (prev_bb->exit_state, current_bb->entry_state)) 1022 { 1023 /* Candidate for .cfi_restore_state found. */ 1024 ginsn = bb_get_first_ginsn (current_bb); 1025 scfi_op_add_cfi_restore_state (ginsn); 1026 /* Memorize current_bb now to find location for its remember state 1027 later. */ 1028 restore_bbs[i] = current_bb; 1029 } 1030 else 1031 { 1032 bb_for_each_edge (current_bb, gedge) 1033 { 1034 dst_bb = gedge->dst_bb; 1035 for (j = 0; j < gcfg->num_gbbs; j++) 1036 if (restore_bbs[j] == dst_bb) 1037 { 1038 ginsn = bb_get_last_ginsn (current_bb); 1039 scfi_op_add_cfi_remember_state (ginsn); 1040 /* Remove the memorised restore_bb from the list. */ 1041 restore_bbs[j] = NULL; 1042 break; 1043 } 1044 } 1045 } 1046 i--; 1047 } 1048 1049 /* All .cfi_restore_state pseudo-ops must have a corresponding 1050 .cfi_remember_state by now. */ 1051 for (j = 0; j < gcfg->num_gbbs; j++) 1052 if (restore_bbs[j] != NULL) 1053 { 1054 ret = 1; 1055 break; 1056 } 1057 1058 free (restore_bbs); 1059 free (prog_order_bbs); 1060 1061 return ret; 1062} 1063 1064/* Synthesize DWARF CFI for a function. */ 1065 1066int 1067scfi_synthesize_dw2cfi (const symbolS *func, gcfgS *gcfg, gbbS *root_bb) 1068{ 1069 int ret; 1070 scfi_stateS *init_state; 1071 1072 init_state = XCNEW (scfi_stateS); 1073 init_state->traceable_p = true; 1074 1075 /* Traverse the input GCFG and perform forward flow of information. 1076 Update the scfi_op(s) per ginsn. */ 1077 ret = forward_flow_scfi_state (gcfg, root_bb, init_state); 1078 if (ret) 1079 { 1080 as_bad (_("SCFI: forward pass failed for func '%s'"), S_GET_NAME (func)); 1081 goto end; 1082 } 1083 1084 ret = backward_flow_scfi_state (func, gcfg); 1085 if (ret) 1086 { 1087 as_bad (_("SCFI: backward pass failed for func '%s'"), S_GET_NAME (func)); 1088 goto end; 1089 } 1090 1091end: 1092 free (init_state); 1093 return ret; 1094} 1095 1096static int 1097handle_scfi_dot_cfi (ginsnS *ginsn) 1098{ 1099 scfi_opS *op; 1100 1101 /* Nothing to do. */ 1102 if (!ginsn->scfi_ops) 1103 return 0; 1104 1105 op = *ginsn->scfi_ops; 1106 if (!op) 1107 goto bad; 1108 1109 while (op) 1110 { 1111 switch (op->dw2cfi_op) 1112 { 1113 case DW_CFA_def_cfa_register: 1114 scfi_dot_cfi (DW_CFA_def_cfa_register, op->loc.base, 0, 0, NULL, 1115 ginsn->sym); 1116 break; 1117 case DW_CFA_def_cfa_offset: 1118 scfi_dot_cfi (DW_CFA_def_cfa_offset, op->loc.base, 0, 1119 op->loc.offset, NULL, ginsn->sym); 1120 break; 1121 case DW_CFA_def_cfa: 1122 scfi_dot_cfi (DW_CFA_def_cfa, op->loc.base, 0, op->loc.offset, 1123 NULL, ginsn->sym); 1124 break; 1125 case DW_CFA_offset: 1126 scfi_dot_cfi (DW_CFA_offset, op->reg, 0, op->loc.offset, NULL, 1127 ginsn->sym); 1128 break; 1129 case DW_CFA_restore: 1130 scfi_dot_cfi (DW_CFA_restore, op->reg, 0, 0, NULL, ginsn->sym); 1131 break; 1132 case DW_CFA_remember_state: 1133 scfi_dot_cfi (DW_CFA_remember_state, 0, 0, 0, NULL, ginsn->sym); 1134 break; 1135 case DW_CFA_restore_state: 1136 scfi_dot_cfi (DW_CFA_restore_state, 0, 0, 0, NULL, ginsn->sym); 1137 break; 1138 case CFI_label: 1139 scfi_dot_cfi (CFI_label, 0, 0, 0, op->op_data->name, ginsn->sym); 1140 break; 1141 case CFI_signal_frame: 1142 scfi_dot_cfi (CFI_signal_frame, 0, 0, 0, NULL, ginsn->sym); 1143 break; 1144 default: 1145 goto bad; 1146 break; 1147 } 1148 op = op->next; 1149 } 1150 1151 return 0; 1152bad: 1153 as_bad (_("SCFI: Invalid DWARF CFI opcode data")); 1154 return 1; 1155} 1156 1157/* Emit Synthesized DWARF CFI. */ 1158 1159int 1160scfi_emit_dw2cfi (const symbolS *func) 1161{ 1162 struct frch_ginsn_data *frch_gdata; 1163 ginsnS* ginsn = NULL; 1164 1165 frch_gdata = frchain_now->frch_ginsn_data; 1166 ginsn = frch_gdata->gins_rootP; 1167 1168 while (ginsn) 1169 { 1170 switch (ginsn->type) 1171 { 1172 case GINSN_TYPE_SYMBOL: 1173 /* .cfi_startproc and .cfi_endproc pseudo-ops. */ 1174 if (GINSN_F_FUNC_BEGIN_P (ginsn)) 1175 { 1176 scfi_dot_cfi_startproc (frch_gdata->start_addr); 1177 break; 1178 } 1179 else if (GINSN_F_FUNC_END_P (ginsn)) 1180 { 1181 scfi_dot_cfi_endproc (ginsn->sym); 1182 break; 1183 } 1184 /* Fall through. */ 1185 case GINSN_TYPE_ADD: 1186 case GINSN_TYPE_AND: 1187 case GINSN_TYPE_CALL: 1188 case GINSN_TYPE_JUMP: 1189 case GINSN_TYPE_JUMP_COND: 1190 case GINSN_TYPE_MOV: 1191 case GINSN_TYPE_LOAD: 1192 case GINSN_TYPE_PHANTOM: 1193 case GINSN_TYPE_STORE: 1194 case GINSN_TYPE_SUB: 1195 case GINSN_TYPE_OTHER: 1196 case GINSN_TYPE_RETURN: 1197 1198 /* For all other SCFI ops, invoke the handler. */ 1199 if (ginsn->scfi_ops) 1200 handle_scfi_dot_cfi (ginsn); 1201 break; 1202 1203 default: 1204 /* No other GINSN_TYPE_* expected. */ 1205 as_bad (_("SCFI: bad ginsn for func '%s'"), 1206 S_GET_NAME (func)); 1207 break; 1208 } 1209 ginsn = ginsn->next; 1210 } 1211 return 0; 1212} 1213 1214#else 1215 1216int 1217scfi_emit_dw2cfi (const symbolS *func ATTRIBUTE_UNUSED) 1218{ 1219 as_bad (_("SCFI: unsupported for target")); 1220 return 1; 1221} 1222 1223int 1224scfi_synthesize_dw2cfi (const symbolS *func ATTRIBUTE_UNUSED, 1225 gcfgS *gcfg ATTRIBUTE_UNUSED, 1226 gbbS *root_bb ATTRIBUTE_UNUSED) 1227{ 1228 as_bad (_("SCFI: unsupported for target")); 1229 return 1; 1230} 1231 1232#endif /* defined (TARGET_USE_SCFI) && defined (TARGET_USE_GINSN). */ 1233