nm: Replace --with-symbol-versions with --without-symbol-versions in --help output
[binutils-gdb.git] / gas / scfi.c
blob37cc85cfed7ce1a1b8a79f7dd6bebacc97e9145b
1 /* scfi.c - Support for synthesizing DWARF CFI for hand-written asm.
2 Copyright (C) 2023 Free Software Foundation, Inc.
4 This file is part of GAS, the GNU Assembler.
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.
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.
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. */
21 #include "as.h"
22 #include "scfi.h"
23 #include "subsegs.h"
24 #include "scfidw2gen.h"
25 #include "dw2gencfi.h"
27 #if defined (TARGET_USE_SCFI) && defined (TARGET_USE_GINSN)
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)
38 #define REG_INVALID ((unsigned int)-1)
40 enum cfi_reglocstate
42 CFI_UNDEFINED,
43 CFI_IN_REG,
44 CFI_ON_STACK
47 /* Location at which CFI register is saved.
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. */
53 struct cfi_regloc
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;
63 typedef struct cfi_regloc cfi_reglocS;
65 struct scfi_op_data
67 const char *name;
70 typedef struct scfi_op_data scfi_op_dataS;
72 /* SCFI operation.
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. */
78 struct scfi_op
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;
94 /* SCFI State - accumulated unwind information at a PC.
96 SCFI state is the accumulated unwind information encompassing:
97 - REG_SP, REG_FP,
98 - RA, and
99 - all callee-saved registers.
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. */
105 struct scfi_state
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;
118 /* Initialize a new SCFI op. */
120 static scfi_opS *
121 init_scfi_op (void)
123 scfi_opS *op = XCNEW (scfi_opS);
125 return op;
128 /* Free the SCFI ops, given the HEAD of the list. */
130 void
131 scfi_ops_cleanup (scfi_opS **head)
133 scfi_opS *op;
134 scfi_opS *next;
136 if (!head || !*head)
137 return;
139 op = *head;
140 next = op->next;
142 while (op)
144 free (op);
145 op = next;
146 next = op ? op->next : NULL;
150 /* Compare two SCFI states. */
152 static int
153 cmp_scfi_state (scfi_stateS *state1, scfi_stateS *state2)
155 int ret;
157 if (!state1 || !state2)
158 ret = 1;
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);
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;
173 ret |= state1->traceable_p != state2->traceable_p;
175 return ret;
178 #if 0
179 static void
180 scfi_state_update_reg (scfi_stateS *state, uint32_t dst, uint32_t base,
181 int32_t offset)
183 if (dst >= MAX_NUM_SCFI_REGS)
184 return;
186 state->regs[dst].base = base;
187 state->regs[dst].offset = offset;
189 #endif
191 /* Update the SCFI state of REG as available on execution stack at OFFSET
192 from REG_CFA (BASE).
194 Note that BASE must be REG_CFA, because any other base (REG_SP, REG_FP)
195 is by definition transitory in the function. */
197 static void
198 scfi_state_save_reg (scfi_stateS *state, unsigned int reg, unsigned int base,
199 offsetT offset)
201 if (reg >= MAX_NUM_SCFI_REGS)
202 return;
204 gas_assert (base == REG_CFA);
206 state->regs[reg].base = base;
207 state->regs[reg].offset = offset;
208 state->regs[reg].state = CFI_ON_STACK;
211 static void
212 scfi_state_restore_reg (scfi_stateS *state, unsigned int reg)
214 if (reg >= MAX_NUM_SCFI_REGS)
215 return;
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);
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;
228 /* Identify if the given GAS instruction GINSN saves a register
229 (of interest) on stack. */
231 static bool
232 ginsn_scfi_save_reg_p (ginsnS *ginsn, scfi_stateS *state)
234 bool save_reg_p = false;
235 struct ginsn_src *src;
236 struct ginsn_dst *dst;
238 src = ginsn_get_src1 (ginsn);
239 dst = ginsn_get_dst (ginsn);
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;
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;
260 return save_reg_p;
263 /* Identify if the given GAS instruction GINSN restores a register
264 (of interest) on stack. */
266 static bool
267 ginsn_scfi_restore_reg_p (ginsnS *ginsn, scfi_stateS *state)
269 bool restore_reg_p = false;
270 struct ginsn_dst *dst;
271 struct ginsn_src *src1;
273 dst = ginsn_get_dst (ginsn);
274 src1 = ginsn_get_src1 (ginsn);
276 if (!ginsn_track_reg_p (ginsn_get_dst_reg (dst), GINSN_GEN_SCFI))
277 return restore_reg_p;
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;
292 return restore_reg_p;
295 /* Append the SCFI operation OP to the list of SCFI operations in the
296 given GINSN. */
298 static int
299 ginsn_append_scfi_op (ginsnS *ginsn, scfi_opS *op)
301 scfi_opS *sop;
303 if (!ginsn || !op)
304 return 1;
306 if (!ginsn->scfi_ops)
308 ginsn->scfi_ops = XCNEW (scfi_opS *);
309 *ginsn->scfi_ops = op;
311 else
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;
319 sop->next = op;
321 ginsn->num_scfi_ops++;
323 return 0;
326 static void
327 scfi_op_add_def_cfa_reg (scfi_stateS *state, ginsnS *ginsn, unsigned int reg)
329 scfi_opS *op = NULL;
331 state->regs[REG_CFA].base = reg;
333 op = init_scfi_op ();
335 op->dw2cfi_op = DW_CFA_def_cfa_register;
336 op->reg = REG_CFA;
337 op->loc = state->regs[REG_CFA];
339 ginsn_append_scfi_op (ginsn, op);
342 static void
343 scfi_op_add_cfa_offset_inc (scfi_stateS *state, ginsnS *ginsn, offsetT num)
345 scfi_opS *op = NULL;
347 state->regs[REG_CFA].offset -= num;
349 op = init_scfi_op ();
351 op->dw2cfi_op = DW_CFA_def_cfa_offset;
352 op->reg = REG_CFA;
353 op->loc = state->regs[REG_CFA];
355 ginsn_append_scfi_op (ginsn, op);
358 static void
359 scfi_op_add_cfa_offset_dec (scfi_stateS *state, ginsnS *ginsn, offsetT num)
361 scfi_opS *op = NULL;
363 state->regs[REG_CFA].offset += num;
365 op = init_scfi_op ();
367 op->dw2cfi_op = DW_CFA_def_cfa_offset;
368 op->reg = REG_CFA;
369 op->loc = state->regs[REG_CFA];
371 ginsn_append_scfi_op (ginsn, op);
374 static void
375 scfi_op_add_def_cfa (scfi_stateS *state, ginsnS *ginsn, unsigned int reg,
376 offsetT num)
378 scfi_opS *op = NULL;
380 state->regs[REG_CFA].base = reg;
381 state->regs[REG_CFA].offset = num;
383 op = init_scfi_op ();
385 op->dw2cfi_op = DW_CFA_def_cfa;
386 op->reg = REG_CFA;
387 op->loc = state->regs[REG_CFA];
389 ginsn_append_scfi_op (ginsn, op);
392 static void
393 scfi_op_add_cfi_offset (scfi_stateS *state, ginsnS *ginsn, unsigned int reg)
395 scfi_opS *op = NULL;
397 op = init_scfi_op ();
399 op->dw2cfi_op = DW_CFA_offset;
400 op->reg = reg;
401 op->loc = state->regs[reg];
403 ginsn_append_scfi_op (ginsn, op);
406 static void
407 scfi_op_add_cfa_restore (ginsnS *ginsn, unsigned int reg)
409 scfi_opS *op = NULL;
411 op = init_scfi_op ();
413 op->dw2cfi_op = DW_CFA_restore;
414 op->reg = reg;
415 op->loc.base = REG_INVALID;
416 op->loc.offset = 0;
418 ginsn_append_scfi_op (ginsn, op);
421 static void
422 scfi_op_add_cfi_remember_state (ginsnS *ginsn)
424 scfi_opS *op = NULL;
426 op = init_scfi_op ();
428 op->dw2cfi_op = DW_CFA_remember_state;
430 ginsn_append_scfi_op (ginsn, op);
433 static void
434 scfi_op_add_cfi_restore_state (ginsnS *ginsn)
436 scfi_opS *op = NULL;
438 op = init_scfi_op ();
440 op->dw2cfi_op = DW_CFA_restore_state;
442 /* FIXME - add to the beginning of the scfi_ops. */
443 ginsn_append_scfi_op (ginsn, op);
446 void
447 scfi_op_add_cfi_label (ginsnS *ginsn, const char *name)
449 scfi_opS *op = NULL;
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;
456 ginsn_append_scfi_op (ginsn, op);
459 void
460 scfi_op_add_signal_frame (ginsnS *ginsn)
462 scfi_opS *op = NULL;
464 op = init_scfi_op ();
465 op->dw2cfi_op = CFI_signal_frame;
467 ginsn_append_scfi_op (ginsn, op);
470 static int
471 verify_heuristic_traceable_reg_fp (ginsnS *ginsn, scfi_stateS *state)
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;
479 src1 = ginsn_get_src1 (ginsn);
480 src2 = ginsn_get_src2 (ginsn);
481 dst = ginsn_get_dst (ginsn);
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.
487 The SCFI machinery in GAS is based on some heuristics:
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). */
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)
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;
521 if (fp_traceable_p)
522 as_bad_where (ginsn->file, ginsn->line,
523 _("SCFI: usage of REG_FP as scratch not supported"));
525 return fp_traceable_p;
528 static int
529 verify_heuristic_traceable_stack_manipulation (ginsnS *ginsn,
530 scfi_stateS *state)
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;
539 src1 = ginsn_get_src1 (ginsn);
540 src2 = ginsn_get_src2 (ginsn);
541 dst = ginsn_get_dst (ginsn);
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.
547 The SCFI machinery in GAS is based on some heuristics:
549 - Rule 1 The base register for CFA tracking may be either REG_SP or
550 REG_FP.
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. */
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)
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)
569 possibly_untraceable = true;
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)
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;
596 else if (ginsn_scfi_restore_reg_p (ginsn, state) && !state->traceable_p)
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;
606 if (possibly_untraceable)
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)
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;
627 if (sp_untraceable_p)
628 as_bad_where (ginsn->file, ginsn->line,
629 _("SCFI: unsupported stack manipulation pattern"));
631 return sp_untraceable_p;
634 static int
635 verify_heuristic_symmetrical_restore_reg (scfi_stateS *state, ginsnS* ginsn)
637 int sym_restore = true;
638 offsetT expected_offset = 0;
639 struct ginsn_src *src1;
640 struct ginsn_dst *dst;
641 unsigned int reg;
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
649 body of func which uses reg1 , reg2 as scratch,
650 and may be even spills them to stack.
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
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);
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;
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);
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)))
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));
686 sym_restore = (expected_offset == state->regs[reg].offset);
688 return sym_restore;
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. */
695 static int
696 gen_scfi_ops (ginsnS *ginsn, scfi_stateS *state)
698 int ret = 0;
699 offsetT offset;
700 struct ginsn_src *src1;
701 struct ginsn_src *src2;
702 struct ginsn_dst *dst;
704 if (!ginsn || !state)
705 ret = 1;
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))
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;
717 src1 = ginsn_get_src1 (ginsn);
718 src2 = ginsn_get_src2 (ginsn);
719 dst = ginsn_get_dst (ginsn);
721 ret = verify_heuristic_traceable_stack_manipulation (ginsn, state);
722 if (ret)
723 return ret;
725 ret = verify_heuristic_traceable_reg_fp (ginsn, state);
726 if (ret)
727 return ret;
729 switch (ginsn->dst.type)
731 case GINSN_DST_REG:
732 switch (ginsn->type)
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)
740 /* mov %rsp, %rbp. */
741 scfi_op_add_def_cfa_reg (state, ginsn, ginsn_get_dst_reg (dst));
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)
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;
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))
758 /* mov disp(%rsp), reg. */
759 /* mov disp(%rbp), reg. */
760 if (verify_heuristic_symmetrical_restore_reg (state, ginsn))
762 scfi_state_restore_reg (state, ginsn_get_dst_reg (dst));
763 scfi_op_add_cfa_restore (ginsn, ginsn_get_dst_reg (dst));
765 else
766 as_warn_where (ginsn->file, ginsn->line,
767 _("SCFI: asymetrical register restore"));
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)
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;
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)
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)
790 state->stack_size = -state->scratch[ginsn_get_src_reg (src1)].offset;
791 state->traceable_p = true;
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
800 break;
801 case GINSN_TYPE_SUB:
802 if (ginsn_get_src_reg (src1) == REG_SP
803 && ginsn_get_dst_reg (dst) == REG_SP)
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)
810 /* push reg. */
811 scfi_op_add_cfa_offset_dec (state, ginsn, ginsn_get_src_imm (src2));
814 break;
815 case GINSN_TYPE_ADD:
816 if (ginsn_get_src_reg (src1) == REG_SP
817 && ginsn_get_dst_reg (dst) == REG_SP)
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)
826 scfi_op_add_cfa_offset_inc (state, ginsn, ginsn_get_src_imm (src2));
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)
833 /* FIXME - what is this for ? */
834 state->stack_size = 0 - (state->regs[REG_FP].offset + ginsn_get_src_imm (src2));
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)))
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)
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));
853 if (ginsn_track_reg_p (ginsn_get_dst_reg (dst), GINSN_GEN_SCFI))
855 if (verify_heuristic_symmetrical_restore_reg (state, ginsn))
857 scfi_state_restore_reg (state, ginsn_get_dst_reg (dst));
858 scfi_op_add_cfa_restore (ginsn, ginsn_get_dst_reg (dst));
860 else
861 as_warn_where (ginsn->file, ginsn->line,
862 _("SCFI: asymetrical register restore"));
865 break;
866 default:
867 break;
869 break;
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))
887 if (ginsn_get_dst_reg (dst) == REG_SP)
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));
894 else if (ginsn_get_dst_reg (dst) == REG_FP)
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));
903 break;
905 default:
906 /* Skip GINSN_DST_UNKNOWN and GINSN_DST_MEM as they are uninteresting
907 currently for SCFI. */
908 break;
911 return ret;
914 /* Recursively perform forward flow of the (unwind information) SCFI state
915 starting at basic block GBB.
917 The forward flow process propagates the SCFI state at exit of a basic block
918 to the successor basic block.
920 Returns error code, if any. */
922 static int
923 forward_flow_scfi_state (gcfgS *gcfg, gbbS *gbb, scfi_stateS *state)
925 ginsnS *ginsn;
926 gbbS *prev_bb;
927 gedgeS *gedge = NULL;
928 int ret = 0;
930 if (gbb->visited)
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;
939 gbb->visited = true;
941 gbb->entry_state = XCNEW (scfi_stateS);
942 memcpy (gbb->entry_state, state, sizeof (scfi_stateS));
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)
948 ret = gen_scfi_ops (ginsn, state);
949 if (ret)
950 goto fail;
953 gbb->exit_state = XCNEW (scfi_stateS);
954 memcpy (gbb->exit_state, state, sizeof (scfi_stateS));
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)
961 bb_for_each_edge(gbb, gedge)
963 gbb = gedge->dst_bb;
964 if (gbb->visited)
966 ret = cmp_scfi_state (gbb->entry_state, state);
967 if (ret)
968 goto fail;
971 if (!gedge->visited)
973 gedge->visited = true;
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;
985 return 0;
987 fail:
989 if (gedge)
990 gedge->visited = true;
991 return 1;
994 static int
995 backward_flow_scfi_state (const symbolS *func ATTRIBUTE_UNUSED, gcfgS *gcfg)
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;
1005 int ret = 0;
1006 uint64_t i, j;
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);
1013 gcfg_get_bbs_in_prog_order (gcfg, prog_order_bbs);
1015 i = gcfg->num_gbbs - 1;
1016 /* Traverse in reverse program order. */
1017 while (i > 0)
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))
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;
1030 else
1032 bb_for_each_edge (current_bb, gedge)
1034 dst_bb = gedge->dst_bb;
1035 for (j = 0; j < gcfg->num_gbbs; j++)
1036 if (restore_bbs[j] == dst_bb)
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;
1046 i--;
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)
1054 ret = 1;
1055 break;
1058 free (restore_bbs);
1059 free (prog_order_bbs);
1061 return ret;
1064 /* Synthesize DWARF CFI for a function. */
1067 scfi_synthesize_dw2cfi (const symbolS *func, gcfgS *gcfg, gbbS *root_bb)
1069 int ret;
1070 scfi_stateS *init_state;
1072 init_state = XCNEW (scfi_stateS);
1073 init_state->traceable_p = true;
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)
1080 as_bad (_("SCFI: forward pass failed for func '%s'"), S_GET_NAME (func));
1081 goto end;
1084 ret = backward_flow_scfi_state (func, gcfg);
1085 if (ret)
1087 as_bad (_("SCFI: backward pass failed for func '%s'"), S_GET_NAME (func));
1088 goto end;
1091 end:
1092 free (init_state);
1093 return ret;
1096 static int
1097 handle_scfi_dot_cfi (ginsnS *ginsn)
1099 scfi_opS *op;
1101 /* Nothing to do. */
1102 if (!ginsn->scfi_ops)
1103 return 0;
1105 op = *ginsn->scfi_ops;
1106 if (!op)
1107 goto bad;
1109 while (op)
1111 switch (op->dw2cfi_op)
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;
1148 op = op->next;
1151 return 0;
1152 bad:
1153 as_bad (_("SCFI: Invalid DWARF CFI opcode data"));
1154 return 1;
1157 /* Emit Synthesized DWARF CFI. */
1160 scfi_emit_dw2cfi (const symbolS *func)
1162 struct frch_ginsn_data *frch_gdata;
1163 ginsnS* ginsn = NULL;
1165 frch_gdata = frchain_now->frch_ginsn_data;
1166 ginsn = frch_gdata->gins_rootP;
1168 while (ginsn)
1170 switch (ginsn->type)
1172 case GINSN_TYPE_SYMBOL:
1173 /* .cfi_startproc and .cfi_endproc pseudo-ops. */
1174 if (GINSN_F_FUNC_BEGIN_P (ginsn))
1176 scfi_dot_cfi_startproc (frch_gdata->start_addr);
1177 break;
1179 else if (GINSN_F_FUNC_END_P (ginsn))
1181 scfi_dot_cfi_endproc (ginsn->sym);
1182 break;
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:
1198 /* For all other SCFI ops, invoke the handler. */
1199 if (ginsn->scfi_ops)
1200 handle_scfi_dot_cfi (ginsn);
1201 break;
1203 default:
1204 /* No other GINSN_TYPE_* expected. */
1205 as_bad (_("SCFI: bad ginsn for func '%s'"),
1206 S_GET_NAME (func));
1207 break;
1209 ginsn = ginsn->next;
1211 return 0;
1214 #else
1217 scfi_emit_dw2cfi (const symbolS *func ATTRIBUTE_UNUSED)
1219 as_bad (_("SCFI: unsupported for target"));
1220 return 1;
1224 scfi_synthesize_dw2cfi (const symbolS *func ATTRIBUTE_UNUSED,
1225 gcfgS *gcfg ATTRIBUTE_UNUSED,
1226 gbbS *root_bb ATTRIBUTE_UNUSED)
1228 as_bad (_("SCFI: unsupported for target"));
1229 return 1;
1232 #endif /* defined (TARGET_USE_SCFI) && defined (TARGET_USE_GINSN). */