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)
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
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)
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. */
55 /* Base reg ID (DWARF register number). */
57 /* Location as offset from the CFA. */
59 /* Current state of the CFI register. */
60 enum cfi_reglocstate state
;
63 typedef struct cfi_regloc cfi_reglocS
;
70 typedef struct scfi_op_data scfi_op_dataS
;
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. */
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. */
84 /* Location of the reg. */
86 /* DWARF CFI opcode. */
88 /* Some SCFI ops, e.g., for CFI_label, may need to carry additional data. */
89 scfi_op_dataS
*op_data
;
94 /* SCFI State - accumulated unwind information at a PC.
96 SCFI state is the accumulated unwind information encompassing:
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. */
107 cfi_reglocS regs
[MAX_NUM_SCFI_REGS
];
108 cfi_reglocS scratch
[MAX_NUM_SCFI_REGS
];
109 /* Current 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. */
118 /* Initialize a new SCFI op. */
123 scfi_opS
*op
= XCNEW (scfi_opS
);
128 /* Free the SCFI ops, given the HEAD of the list. */
131 scfi_ops_cleanup (scfi_opS
**head
)
147 next
= op
? op
->next
: NULL
;
153 /* Compare two SCFI states. */
156 cmp_scfi_state (scfi_stateS
*state1
, scfi_stateS
*state2
)
160 if (!state1
|| !state2
)
163 /* Skip comparing the scratch[] value of registers. The user visible
164 unwind information is derived from the regs[] from the SCFI state. */
165 ret
= memcmp (state1
->regs
, state2
->regs
,
166 sizeof (cfi_reglocS
) * MAX_NUM_SCFI_REGS
);
168 /* For user functions which perform dynamic stack allocation, after switching
169 t REG_FP based CFA tracking, it is perfectly possible to have stack usage
170 in some control flows. Further, the different control flows may even not
171 have the same idea of CFA tracking (likely later necessitating generation
172 of .cfi_remember_state / .cfi_restore_state pair). */
173 ret
|= state1
->regs
[REG_CFA
].base
!= state2
->regs
[REG_CFA
].base
;
175 if (!ret
&& state1
->regs
[REG_CFA
].base
== REG_SP
)
176 ret
|= state1
->stack_size
!= state2
->stack_size
;
178 ret
|= state1
->traceable_p
!= state2
->traceable_p
;
185 scfi_state_update_reg (scfi_stateS
*state
, uint32_t dst
, uint32_t base
,
188 if (dst
>= MAX_NUM_SCFI_REGS
)
191 state
->regs
[dst
].base
= base
;
192 state
->regs
[dst
].offset
= offset
;
196 /* Update the SCFI state of REG as available on execution stack at OFFSET
199 Note that BASE must be REG_CFA, because any other base (REG_SP, REG_FP)
200 is by definition transitory in the function. */
203 scfi_state_save_reg (scfi_stateS
*state
, unsigned int reg
, unsigned int base
,
206 if (reg
>= MAX_NUM_SCFI_REGS
)
209 gas_assert (base
== REG_CFA
);
211 state
->regs
[reg
].base
= base
;
212 state
->regs
[reg
].offset
= offset
;
213 state
->regs
[reg
].state
= CFI_ON_STACK
;
217 scfi_state_restore_reg (scfi_stateS
*state
, unsigned int reg
)
219 if (reg
>= MAX_NUM_SCFI_REGS
)
222 /* Sanity check. See Rule 4. */
223 gas_assert (state
->regs
[reg
].state
== CFI_ON_STACK
);
224 gas_assert (state
->regs
[reg
].base
== REG_CFA
);
226 /* PS: the register may still be on stack much after the restore. Reset the
227 SCFI state to CFI_UNDEFINED, however, to indicate that the most updated
228 source of value is register itself from here onwards. */
229 state
->regs
[reg
].base
= 0;
230 state
->regs
[reg
].offset
= 0;
231 state
->regs
[reg
].state
= CFI_UNDEFINED
;
234 /* Identify if the given GAS instruction GINSN saves a register
235 (of interest) on stack. */
238 ginsn_scfi_save_reg_p (ginsnS
*ginsn
, scfi_stateS
*state
)
240 bool save_reg_p
= false;
241 struct ginsn_src
*src
;
242 struct ginsn_dst
*dst
;
244 src
= ginsn_get_src1 (ginsn
);
245 dst
= ginsn_get_dst (ginsn
);
247 /* The first save to stack of callee-saved register is deemed as
249 if (!ginsn_track_reg_p (ginsn_get_src_reg (src
), GINSN_GEN_SCFI
)
250 || state
->regs
[ginsn_get_src_reg (src
)].state
== CFI_ON_STACK
)
253 /* A register save insn may be an indirect mov. */
254 if (ginsn
->type
== GINSN_TYPE_MOV
255 && ginsn_get_dst_type (dst
) == GINSN_DST_INDIRECT
256 && (ginsn_get_dst_reg (dst
) == REG_SP
257 || (ginsn_get_dst_reg (dst
) == REG_FP
258 && state
->regs
[REG_CFA
].base
== REG_FP
)))
260 /* or an explicit store to stack. */
261 else if (ginsn
->type
== GINSN_TYPE_STORE
262 && ginsn_get_dst_type (dst
) == GINSN_DST_INDIRECT
263 && ginsn_get_dst_reg (dst
) == REG_SP
)
269 /* Identify if the given GAS instruction GINSN restores a register
270 (of interest) on stack. */
273 ginsn_scfi_restore_reg_p (ginsnS
*ginsn
, scfi_stateS
*state
)
275 bool restore_reg_p
= false;
276 struct ginsn_dst
*dst
;
277 struct ginsn_src
*src1
;
279 dst
= ginsn_get_dst (ginsn
);
280 src1
= ginsn_get_src1 (ginsn
);
282 if (!ginsn_track_reg_p (ginsn_get_dst_reg (dst
), GINSN_GEN_SCFI
))
283 return restore_reg_p
;
285 /* A register restore insn may be an indirect mov... */
286 if (ginsn
->type
== GINSN_TYPE_MOV
287 && ginsn_get_src_type (src1
) == GINSN_SRC_INDIRECT
288 && (ginsn_get_src_reg (src1
) == REG_SP
289 || (ginsn_get_src_reg (src1
) == REG_FP
290 && state
->regs
[REG_CFA
].base
== REG_FP
)))
291 restore_reg_p
= true;
292 /* ...or an explicit load from stack. */
293 else if (ginsn
->type
== GINSN_TYPE_LOAD
294 && ginsn_get_src_type (src1
) == GINSN_SRC_INDIRECT
295 && ginsn_get_src_reg (src1
) == REG_SP
)
296 restore_reg_p
= true;
298 return restore_reg_p
;
301 /* Append the SCFI operation OP to the list of SCFI operations in the
305 ginsn_append_scfi_op (ginsnS
*ginsn
, scfi_opS
*op
)
312 if (!ginsn
->scfi_ops
)
314 ginsn
->scfi_ops
= XCNEW (scfi_opS
*);
315 *ginsn
->scfi_ops
= op
;
319 /* Add to tail. Most ginsns have a single SCFI operation,
320 so this traversal for every insertion is acceptable for now. */
321 sop
= *ginsn
->scfi_ops
;
327 ginsn
->num_scfi_ops
++;
333 scfi_op_add_def_cfa_reg (scfi_stateS
*state
, ginsnS
*ginsn
, unsigned int reg
)
337 state
->regs
[REG_CFA
].base
= reg
;
339 op
= init_scfi_op ();
341 op
->dw2cfi_op
= DW_CFA_def_cfa_register
;
343 op
->loc
= state
->regs
[REG_CFA
];
345 ginsn_append_scfi_op (ginsn
, op
);
349 scfi_op_add_cfa_offset_inc (scfi_stateS
*state
, ginsnS
*ginsn
, offsetT num
)
353 state
->regs
[REG_CFA
].offset
-= num
;
355 op
= init_scfi_op ();
357 op
->dw2cfi_op
= DW_CFA_def_cfa_offset
;
359 op
->loc
= state
->regs
[REG_CFA
];
361 ginsn_append_scfi_op (ginsn
, op
);
365 scfi_op_add_cfa_offset_dec (scfi_stateS
*state
, ginsnS
*ginsn
, offsetT num
)
369 state
->regs
[REG_CFA
].offset
+= num
;
371 op
= init_scfi_op ();
373 op
->dw2cfi_op
= DW_CFA_def_cfa_offset
;
375 op
->loc
= state
->regs
[REG_CFA
];
377 ginsn_append_scfi_op (ginsn
, op
);
381 scfi_op_add_def_cfa (scfi_stateS
*state
, ginsnS
*ginsn
, unsigned int reg
,
386 state
->regs
[REG_CFA
].base
= reg
;
387 state
->regs
[REG_CFA
].offset
= num
;
389 op
= init_scfi_op ();
391 op
->dw2cfi_op
= DW_CFA_def_cfa
;
393 op
->loc
= state
->regs
[REG_CFA
];
395 ginsn_append_scfi_op (ginsn
, op
);
399 scfi_op_add_cfi_offset (scfi_stateS
*state
, ginsnS
*ginsn
, unsigned int reg
)
403 op
= init_scfi_op ();
405 op
->dw2cfi_op
= DW_CFA_offset
;
407 op
->loc
= state
->regs
[reg
];
409 ginsn_append_scfi_op (ginsn
, op
);
413 scfi_op_add_cfa_restore (ginsnS
*ginsn
, unsigned int reg
)
417 op
= init_scfi_op ();
419 op
->dw2cfi_op
= DW_CFA_restore
;
421 op
->loc
.base
= REG_INVALID
;
424 ginsn_append_scfi_op (ginsn
, op
);
428 scfi_op_add_cfi_remember_state (ginsnS
*ginsn
)
432 op
= init_scfi_op ();
434 op
->dw2cfi_op
= DW_CFA_remember_state
;
436 ginsn_append_scfi_op (ginsn
, op
);
440 scfi_op_add_cfi_restore_state (ginsnS
*ginsn
)
444 op
= init_scfi_op ();
446 op
->dw2cfi_op
= DW_CFA_restore_state
;
448 /* FIXME - add to the beginning of the scfi_ops. */
449 ginsn_append_scfi_op (ginsn
, op
);
453 scfi_op_add_cfi_label (ginsnS
*ginsn
, const char *name
)
457 op
= init_scfi_op ();
458 op
->dw2cfi_op
= CFI_label
;
459 op
->op_data
= XCNEW (scfi_op_dataS
);
460 op
->op_data
->name
= name
;
462 ginsn_append_scfi_op (ginsn
, op
);
466 scfi_op_add_signal_frame (ginsnS
*ginsn
)
470 op
= init_scfi_op ();
471 op
->dw2cfi_op
= CFI_signal_frame
;
473 ginsn_append_scfi_op (ginsn
, op
);
477 verify_heuristic_traceable_reg_fp (ginsnS
*ginsn
, scfi_stateS
*state
)
479 /* The function uses this variable to issue error to user right away. */
480 int fp_traceable_p
= 0;
481 struct ginsn_dst
*dst
;
482 struct ginsn_src
*src1
;
483 struct ginsn_src
*src2
;
485 src1
= ginsn_get_src1 (ginsn
);
486 src2
= ginsn_get_src2 (ginsn
);
487 dst
= ginsn_get_dst (ginsn
);
489 /* Stack manipulation can be done in a variety of ways. A program may
490 allocate stack statically or may perform dynamic stack allocation in
493 The SCFI machinery in GAS is based on some heuristics:
495 - Rule 3 If the base register for CFA tracking is REG_FP, the program
496 must not clobber REG_FP, unless it is for switch to REG_SP based CFA
497 tracking (via say, a pop %rbp in X86). */
499 /* Check all applicable instructions with dest REG_FP, when the CFA base
500 register is REG_FP. */
501 if (state
->regs
[REG_CFA
].base
== REG_FP
&& ginsn_get_dst_reg (dst
) == REG_FP
)
503 /* Excuse the add/sub with imm usage: They are OK. */
504 if ((ginsn
->type
== GINSN_TYPE_ADD
|| ginsn
->type
== GINSN_TYPE_SUB
)
505 && ginsn_get_src_reg (src1
) == REG_FP
506 && ginsn_get_src_type (src2
) == GINSN_SRC_IMM
)
508 /* REG_FP restore is OK too. */
509 else if (ginsn
->type
== GINSN_TYPE_LOAD
)
511 /* mov's to memory with REG_FP base do not make REG_FP untraceable. */
512 else if (ginsn_get_dst_type (dst
) == GINSN_DST_INDIRECT
513 && (ginsn
->type
== GINSN_TYPE_MOV
514 || ginsn
->type
== GINSN_TYPE_STORE
))
516 /* Manipulations of the values possibly on stack are OK too. */
517 else if ((ginsn
->type
== GINSN_TYPE_ADD
|| ginsn
->type
== GINSN_TYPE_SUB
518 || ginsn
->type
== GINSN_TYPE_AND
)
519 && ginsn_get_dst_type (dst
) == GINSN_DST_INDIRECT
)
521 /* All other ginsns with REG_FP as destination make REG_FP not
528 as_bad_where (ginsn
->file
, ginsn
->line
,
529 _("SCFI: usage of REG_FP as scratch not supported"));
531 return fp_traceable_p
;
535 verify_heuristic_traceable_stack_manipulation (ginsnS
*ginsn
,
538 /* The function uses this variable to issue error to user right away. */
539 int sp_untraceable_p
= 0;
540 bool possibly_untraceable
= false;
541 struct ginsn_dst
*dst
;
542 struct ginsn_src
*src1
;
543 struct ginsn_src
*src2
;
545 src1
= ginsn_get_src1 (ginsn
);
546 src2
= ginsn_get_src2 (ginsn
);
547 dst
= ginsn_get_dst (ginsn
);
549 /* Stack manipulation can be done in a variety of ways. A program may
550 allocate stack statically in prologue or may need to do dynamic stack
553 The SCFI machinery in GAS is based on some heuristics:
555 - Rule 1 The base register for CFA tracking may be either REG_SP or
558 - Rule 2 If the base register for CFA tracking is REG_SP, the precise
559 amount of stack usage (and hence, the value of rsp) must be known at
562 if (ginsn
->type
== GINSN_TYPE_MOV
563 && ginsn_get_dst_type (dst
) == GINSN_DST_REG
564 && ginsn_get_dst_reg (dst
) == REG_SP
565 && ginsn_get_src_type (src1
) == GINSN_SRC_REG
566 /* Exclude mov %rbp, %rsp from this check. */
567 && ginsn_get_src_reg (src1
) != REG_FP
)
569 /* mov %reg, %rsp. */
570 /* A previous mov %rsp, %reg must have been seen earlier for this to be
571 an OK for stack manipulation. */
572 if (state
->scratch
[ginsn_get_src_reg (src1
)].base
!= REG_CFA
573 || state
->scratch
[ginsn_get_src_reg (src1
)].state
!= CFI_IN_REG
)
575 possibly_untraceable
= true;
578 /* Check add/sub/and insn usage when CFA base register is REG_SP.
579 Any stack size manipulation, including stack realignment is not allowed
580 if CFA base register is REG_SP. */
581 else if (ginsn_get_dst_type (dst
) == GINSN_DST_REG
582 && ginsn_get_dst_reg (dst
) == REG_SP
583 && (((ginsn
->type
== GINSN_TYPE_ADD
|| ginsn
->type
== GINSN_TYPE_SUB
)
584 && ginsn_get_src_type (src2
) != GINSN_SRC_IMM
)
585 || ginsn
->type
== GINSN_TYPE_AND
586 || ginsn
->type
== GINSN_TYPE_OTHER
))
587 possibly_untraceable
= true;
588 /* If a register save operation is seen when REG_SP is untraceable,
589 CFI cannot be synthesized for register saves, hence bail out. */
590 else if (ginsn_scfi_save_reg_p (ginsn
, state
) && !state
->traceable_p
)
592 sp_untraceable_p
= 1;
593 /* If, however, the register save is an REG_FP-based, indirect mov
594 like: mov reg, disp(%rbp) and CFA base register is REG_BP,
595 untraceable REG_SP is not a problem. */
596 if (ginsn
->type
== GINSN_TYPE_MOV
597 && ginsn_get_dst_type (dst
) == GINSN_DST_INDIRECT
598 && (ginsn_get_dst_reg (dst
) == REG_FP
599 && state
->regs
[REG_CFA
].base
== REG_FP
))
600 sp_untraceable_p
= 0;
602 else if (ginsn_scfi_restore_reg_p (ginsn
, state
) && !state
->traceable_p
)
604 if (ginsn
->type
== GINSN_TYPE_MOV
605 && ginsn_get_dst_type (dst
) == GINSN_DST_INDIRECT
606 && (ginsn_get_src_reg (src1
) == REG_SP
607 || (ginsn_get_src_reg (src1
) == REG_FP
608 && state
->regs
[REG_CFA
].base
!= REG_FP
)))
609 sp_untraceable_p
= 1;
612 if (possibly_untraceable
)
614 /* See Rule 2. For SP-based CFA, this makes CFA tracking not possible.
615 Propagate now to caller. */
616 if (state
->regs
[REG_CFA
].base
== REG_SP
)
617 sp_untraceable_p
= 1;
618 else if (state
->traceable_p
)
620 /* An extension of Rule 2.
621 For FP-based CFA, this may be a problem *if* certain specific
622 changes to the SCFI state are seen beyond this point, e.g.,
623 register save / restore from stack. */
624 gas_assert (state
->regs
[REG_CFA
].base
== REG_FP
);
625 /* Simply make a note in the SCFI state object for now and
626 continue. Indicate an error when register save / restore
627 for callee-saved registers is seen. */
628 sp_untraceable_p
= 0;
629 state
->traceable_p
= false;
633 if (sp_untraceable_p
)
634 as_bad_where (ginsn
->file
, ginsn
->line
,
635 _("SCFI: unsupported stack manipulation pattern"));
637 return sp_untraceable_p
;
641 verify_heuristic_symmetrical_restore_reg (scfi_stateS
*state
, ginsnS
* ginsn
)
643 int sym_restore
= true;
644 offsetT expected_offset
= 0;
645 struct ginsn_src
*src1
;
646 struct ginsn_dst
*dst
;
649 /* Rule 4: Save and Restore of callee-saved registers must be symmetrical.
650 It is expected that value of the saved register is restored correctly.
655 body of func which uses reg1 , reg2 as scratch,
656 and may be even spills them to stack.
660 It is difficult to verify the Rule 4 in all cases. For the SCFI machinery,
661 it is difficult to separate prologue-epilogue from the body of the function
663 Hence, the SCFI machinery at this time, should only warn on an asymetrical
665 src1
= ginsn_get_src1 (ginsn
);
666 dst
= ginsn_get_dst (ginsn
);
667 reg
= ginsn_get_dst_reg (dst
);
669 /* For non callee-saved registers, calling the API is meaningless. */
670 if (!ginsn_track_reg_p (ginsn_get_dst_reg (dst
), GINSN_GEN_SCFI
))
673 /* The register must have been saved on stack, for sure. */
674 gas_assert (state
->regs
[reg
].state
== CFI_ON_STACK
);
675 gas_assert (state
->regs
[reg
].base
== REG_CFA
);
677 if ((ginsn
->type
== GINSN_TYPE_MOV
678 || ginsn
->type
== GINSN_TYPE_LOAD
)
679 && ginsn_get_src_type (src1
) == GINSN_SRC_INDIRECT
680 && (ginsn_get_src_reg (src1
) == REG_SP
681 || (ginsn_get_src_reg (src1
) == REG_FP
682 && state
->regs
[REG_CFA
].base
== REG_FP
)))
684 /* mov disp(%rsp), reg. */
685 /* mov disp(%rbp), reg. */
686 expected_offset
= (((ginsn_get_src_reg (src1
) == REG_SP
)
688 : state
->regs
[REG_FP
].offset
)
689 + ginsn_get_src_disp (src1
));
692 sym_restore
= (expected_offset
== state
->regs
[reg
].offset
);
697 /* Perform symbolic execution of the GINSN and update its list of scfi_ops.
698 scfi_ops are later used to directly generate the DWARF CFI directives.
699 Also update the SCFI state object STATE for the caller. */
702 gen_scfi_ops (ginsnS
*ginsn
, scfi_stateS
*state
)
706 struct ginsn_src
*src1
;
707 struct ginsn_src
*src2
;
708 struct ginsn_dst
*dst
;
710 if (!ginsn
|| !state
)
713 /* For the first ginsn (of type GINSN_TYPE_SYMBOL) in the gbb, generate
714 the SCFI op with DW_CFA_def_cfa. Note that the register and offset are
716 if (GINSN_F_FUNC_BEGIN_P (ginsn
))
718 scfi_op_add_def_cfa (state
, ginsn
, REG_SP
, SCFI_INIT_CFA_OFFSET
);
719 state
->stack_size
+= SCFI_INIT_CFA_OFFSET
;
723 src1
= ginsn_get_src1 (ginsn
);
724 src2
= ginsn_get_src2 (ginsn
);
725 dst
= ginsn_get_dst (ginsn
);
727 ret
= verify_heuristic_traceable_stack_manipulation (ginsn
, state
);
731 ret
= verify_heuristic_traceable_reg_fp (ginsn
, state
);
735 switch (ginsn
->dst
.type
)
741 if (ginsn_get_src_type (src1
) == GINSN_SRC_REG
742 && ginsn_get_src_reg (src1
) == REG_SP
743 && ginsn_get_dst_reg (dst
) == REG_FP
744 && state
->regs
[REG_CFA
].base
== REG_SP
)
746 /* mov %rsp, %rbp. */
747 scfi_op_add_def_cfa_reg (state
, ginsn
, ginsn_get_dst_reg (dst
));
749 else if (ginsn_get_src_type (src1
) == GINSN_SRC_REG
750 && ginsn_get_src_reg (src1
) == REG_FP
751 && ginsn_get_dst_reg (dst
) == REG_SP
752 && state
->regs
[REG_CFA
].base
== REG_FP
)
754 /* mov %rbp, %rsp. */
755 state
->stack_size
= -state
->regs
[REG_FP
].offset
;
756 scfi_op_add_def_cfa_reg (state
, ginsn
, ginsn_get_dst_reg (dst
));
757 state
->traceable_p
= true;
759 else if (ginsn_get_src_type (src1
) == GINSN_SRC_INDIRECT
760 && (ginsn_get_src_reg (src1
) == REG_SP
761 || ginsn_get_src_reg (src1
) == REG_FP
)
762 && ginsn_track_reg_p (ginsn_get_dst_reg (dst
), GINSN_GEN_SCFI
))
764 /* mov disp(%rsp), reg. */
765 /* mov disp(%rbp), reg. */
766 if (verify_heuristic_symmetrical_restore_reg (state
, ginsn
))
768 scfi_state_restore_reg (state
, ginsn_get_dst_reg (dst
));
769 scfi_op_add_cfa_restore (ginsn
, ginsn_get_dst_reg (dst
));
772 as_warn_where (ginsn
->file
, ginsn
->line
,
773 _("SCFI: asymetrical register restore"));
775 else if (ginsn_get_src_type (src1
) == GINSN_SRC_REG
776 && ginsn_get_dst_type (dst
) == GINSN_DST_REG
777 && ginsn_get_src_reg (src1
) == REG_SP
)
779 /* mov %rsp, %reg. */
780 /* The value of rsp is taken directly from state->stack_size.
781 IMP: The workflow in gen_scfi_ops must keep it updated.
782 PS: Not taking the value from state->scratch[REG_SP] is
784 state
->scratch
[ginsn_get_dst_reg (dst
)].base
= REG_CFA
;
785 state
->scratch
[ginsn_get_dst_reg (dst
)].offset
= -state
->stack_size
;
786 state
->scratch
[ginsn_get_dst_reg (dst
)].state
= CFI_IN_REG
;
788 else if (ginsn_get_src_type (src1
) == GINSN_SRC_REG
789 && ginsn_get_dst_type (dst
) == GINSN_DST_REG
790 && ginsn_get_dst_reg (dst
) == REG_SP
)
792 /* mov %reg, %rsp. */
793 /* Keep the value of REG_SP updated. */
794 if (state
->scratch
[ginsn_get_src_reg (src1
)].state
== CFI_IN_REG
)
796 state
->stack_size
= -state
->scratch
[ginsn_get_src_reg (src1
)].offset
;
797 state
->traceable_p
= true;
800 scfi_state_update_reg (state
, ginsn_get_dst_reg (dst
),
801 state
->scratch
[ginsn_get_src_reg (src1
)].base
,
802 state
->scratch
[ginsn_get_src_reg (src1
)].offset
);
808 if (ginsn_get_src_reg (src1
) == REG_SP
809 && ginsn_get_dst_reg (dst
) == REG_SP
)
811 /* Stack inc/dec offset, when generated due to stack push and pop is
812 target-specific. Use the value encoded in the ginsn. */
813 state
->stack_size
+= ginsn_get_src_imm (src2
);
814 if (state
->regs
[REG_CFA
].base
== REG_SP
)
817 scfi_op_add_cfa_offset_dec (state
, ginsn
, ginsn_get_src_imm (src2
));
822 if (ginsn_get_src_reg (src1
) == REG_SP
823 && ginsn_get_dst_reg (dst
) == REG_SP
)
825 /* Stack inc/dec offset is target-specific. Use the value
826 encoded in the ginsn. */
827 state
->stack_size
-= ginsn_get_src_imm (src2
);
828 /* pop %reg affects CFA offset only if CFA is currently
829 stack-pointer based. */
830 if (state
->regs
[REG_CFA
].base
== REG_SP
)
832 scfi_op_add_cfa_offset_inc (state
, ginsn
, ginsn_get_src_imm (src2
));
835 else if (ginsn_get_src_reg (src1
) == REG_FP
836 && ginsn_get_dst_reg (dst
) == REG_SP
837 && state
->regs
[REG_CFA
].base
== REG_FP
)
839 /* FIXME - what is this for ? */
840 state
->stack_size
= 0 - (state
->regs
[REG_FP
].offset
+ ginsn_get_src_imm (src2
));
843 case GINSN_TYPE_LOAD
:
844 /* If this is a load from stack. */
845 if (ginsn_get_src_type (src1
) == GINSN_SRC_INDIRECT
846 && (ginsn_get_src_reg (src1
) == REG_SP
847 || (ginsn_get_src_reg (src1
) == REG_FP
848 && state
->regs
[REG_CFA
].base
== REG_FP
)))
850 /* pop %rbp when CFA tracking is REG_FP based. */
851 if (ginsn_get_dst_reg (dst
) == REG_FP
852 && state
->regs
[REG_CFA
].base
== REG_FP
)
854 scfi_op_add_def_cfa_reg (state
, ginsn
, REG_SP
);
855 if (state
->regs
[REG_CFA
].offset
!= state
->stack_size
)
856 scfi_op_add_cfa_offset_inc (state
, ginsn
,
857 (state
->regs
[REG_CFA
].offset
- state
->stack_size
));
859 if (ginsn_track_reg_p (ginsn_get_dst_reg (dst
), GINSN_GEN_SCFI
))
861 if (verify_heuristic_symmetrical_restore_reg (state
, ginsn
))
863 scfi_state_restore_reg (state
, ginsn_get_dst_reg (dst
));
864 scfi_op_add_cfa_restore (ginsn
, ginsn_get_dst_reg (dst
));
867 as_warn_where (ginsn
->file
, ginsn
->line
,
868 _("SCFI: asymetrical register restore"));
877 case GINSN_DST_INDIRECT
:
878 /* Some operations with an indirect access to memory (or even to stack)
879 may still be uninteresting for SCFI purpose (e.g, addl %edx, -32(%rsp)
880 in x86). In case of x86_64, these can neither be a register
881 save / unsave, nor can alter the stack size.
882 PS: This condition may need to be revisited for other arches. */
883 if (ginsn
->type
== GINSN_TYPE_ADD
|| ginsn
->type
== GINSN_TYPE_SUB
884 || ginsn
->type
== GINSN_TYPE_AND
)
886 gas_assert (ginsn
->type
== GINSN_TYPE_MOV
887 || ginsn
->type
== GINSN_TYPE_STORE
888 || ginsn
->type
== GINSN_TYPE_LOAD
);
889 /* mov reg, disp(%rbp) */
890 /* mov reg, disp(%rsp) */
891 if (ginsn_scfi_save_reg_p (ginsn
, state
))
893 if (ginsn_get_dst_reg (dst
) == REG_SP
)
895 /* mov reg, disp(%rsp) */
896 offset
= 0 - state
->stack_size
+ ginsn_get_dst_disp (dst
);
897 scfi_state_save_reg (state
, ginsn_get_src_reg (src1
), REG_CFA
, offset
);
898 scfi_op_add_cfi_offset (state
, ginsn
, ginsn_get_src_reg (src1
));
900 else if (ginsn_get_dst_reg (dst
) == REG_FP
)
902 gas_assert (state
->regs
[REG_CFA
].base
== REG_FP
);
903 /* mov reg, disp(%rbp) */
904 offset
= 0 - state
->regs
[REG_CFA
].offset
+ ginsn_get_dst_disp (dst
);
905 scfi_state_save_reg (state
, ginsn_get_src_reg (src1
), REG_CFA
, offset
);
906 scfi_op_add_cfi_offset (state
, ginsn
, ginsn_get_src_reg (src1
));
912 /* Skip GINSN_DST_UNKNOWN and GINSN_DST_MEM as they are uninteresting
913 currently for SCFI. */
920 /* Recursively perform forward flow of the (unwind information) SCFI STATE
921 starting at basic block GBB.
923 The core of forward flow process takes the SCFI state at the entry of a bb
924 and updates it incrementally as per the semantics of each ginsn in the bb.
926 Returns error code, if any. */
929 forward_flow_scfi_state (gcfgS
*gcfg
, gbbS
*gbb
, scfi_stateS
*state
)
933 gedgeS
*gedge
= NULL
;
938 /* Check that the SCFI state is the same as previous. */
939 ret
= cmp_scfi_state (state
, gbb
->entry_state
);
941 as_bad (_("SCFI: Bad CFI propagation perhaps"));
947 gbb
->entry_state
= XCNEW (scfi_stateS
);
948 memcpy (gbb
->entry_state
, state
, sizeof (scfi_stateS
));
950 /* Perform symbolic execution of each ginsn in the gbb and update the
951 scfi_ops list of each ginsn (and also update the STATE object). */
952 bb_for_each_insn(gbb
, ginsn
)
954 ret
= gen_scfi_ops (ginsn
, state
);
959 gbb
->exit_state
= XCNEW (scfi_stateS
);
960 memcpy (gbb
->exit_state
, state
, sizeof (scfi_stateS
));
962 /* Forward flow the SCFI state. Currently, we process the next basic block
963 in DFS order. But any forward traversal order should be fine. */
965 if (gbb
->num_out_gedges
)
967 bb_for_each_edge(gbb
, gedge
)
970 /* Ensure that the state is the one from the exit of the prev bb. */
971 memcpy (state
, prev_bb
->exit_state
, sizeof (scfi_stateS
));
974 ret
= cmp_scfi_state (gbb
->entry_state
, state
);
981 gedge
->visited
= true;
983 /* Entry SCFI state for the destination bb of the edge is the
984 same as the exit SCFI state of the source bb of the edge. */
985 memcpy (state
, prev_bb
->exit_state
, sizeof (scfi_stateS
));
986 ret
= forward_flow_scfi_state (gcfg
, gbb
, state
);
998 gedge
->visited
= true;
1003 backward_flow_scfi_state (const symbolS
*func ATTRIBUTE_UNUSED
, gcfgS
*gcfg
)
1005 gbbS
**prog_order_bbs
;
1011 gedgeS
*gedge
= NULL
;
1016 /* Basic blocks in reverse program order. */
1017 prog_order_bbs
= XCNEWVEC (gbbS
*, gcfg
->num_gbbs
);
1018 /* Basic blocks for which CFI remember op needs to be generated. */
1019 restore_bbs
= XCNEWVEC (gbbS
*, gcfg
->num_gbbs
);
1021 gcfg_get_bbs_in_prog_order (gcfg
, prog_order_bbs
);
1023 i
= gcfg
->num_gbbs
- 1;
1024 /* Traverse in reverse program order. */
1027 current_bb
= prog_order_bbs
[i
];
1028 prev_bb
= prog_order_bbs
[i
-1];
1029 if (cmp_scfi_state (prev_bb
->exit_state
, current_bb
->entry_state
))
1031 /* Candidate for .cfi_restore_state found. */
1032 ginsn
= bb_get_first_ginsn (current_bb
);
1033 scfi_op_add_cfi_restore_state (ginsn
);
1034 /* Memorize current_bb now to find location for its remember state
1036 restore_bbs
[i
] = current_bb
;
1040 bb_for_each_edge (current_bb
, gedge
)
1042 dst_bb
= gedge
->dst_bb
;
1043 for (j
= 0; j
< gcfg
->num_gbbs
; j
++)
1044 if (restore_bbs
[j
] == dst_bb
)
1046 ginsn
= bb_get_last_ginsn (current_bb
);
1047 scfi_op_add_cfi_remember_state (ginsn
);
1048 /* Remove the memorised restore_bb from the list. */
1049 restore_bbs
[j
] = NULL
;
1057 /* All .cfi_restore_state pseudo-ops must have a corresponding
1058 .cfi_remember_state by now. */
1059 for (j
= 0; j
< gcfg
->num_gbbs
; j
++)
1060 if (restore_bbs
[j
] != NULL
)
1067 free (prog_order_bbs
);
1072 /* Synthesize DWARF CFI for a function. */
1075 scfi_synthesize_dw2cfi (const symbolS
*func
, gcfgS
*gcfg
, gbbS
*root_bb
)
1078 scfi_stateS
*init_state
;
1080 init_state
= XCNEW (scfi_stateS
);
1081 init_state
->traceable_p
= true;
1083 /* Traverse the input GCFG and perform forward flow of information.
1084 Update the scfi_op(s) per ginsn. */
1085 ret
= forward_flow_scfi_state (gcfg
, root_bb
, init_state
);
1088 as_bad (_("SCFI: forward pass failed for func '%s'"), S_GET_NAME (func
));
1092 ret
= backward_flow_scfi_state (func
, gcfg
);
1095 as_bad (_("SCFI: backward pass failed for func '%s'"), S_GET_NAME (func
));
1105 handle_scfi_dot_cfi (ginsnS
*ginsn
)
1109 /* Nothing to do. */
1110 if (!ginsn
->scfi_ops
)
1113 op
= *ginsn
->scfi_ops
;
1119 switch (op
->dw2cfi_op
)
1121 case DW_CFA_def_cfa_register
:
1122 scfi_dot_cfi (DW_CFA_def_cfa_register
, op
->loc
.base
, 0, 0, NULL
,
1125 case DW_CFA_def_cfa_offset
:
1126 scfi_dot_cfi (DW_CFA_def_cfa_offset
, op
->loc
.base
, 0,
1127 op
->loc
.offset
, NULL
, ginsn
->sym
);
1129 case DW_CFA_def_cfa
:
1130 scfi_dot_cfi (DW_CFA_def_cfa
, op
->loc
.base
, 0, op
->loc
.offset
,
1134 scfi_dot_cfi (DW_CFA_offset
, op
->reg
, 0, op
->loc
.offset
, NULL
,
1137 case DW_CFA_restore
:
1138 scfi_dot_cfi (DW_CFA_restore
, op
->reg
, 0, 0, NULL
, ginsn
->sym
);
1140 case DW_CFA_remember_state
:
1141 scfi_dot_cfi (DW_CFA_remember_state
, 0, 0, 0, NULL
, ginsn
->sym
);
1143 case DW_CFA_restore_state
:
1144 scfi_dot_cfi (DW_CFA_restore_state
, 0, 0, 0, NULL
, ginsn
->sym
);
1147 scfi_dot_cfi (CFI_label
, 0, 0, 0, op
->op_data
->name
, ginsn
->sym
);
1148 free ((char *) op
->op_data
->name
);
1150 case CFI_signal_frame
:
1151 scfi_dot_cfi (CFI_signal_frame
, 0, 0, 0, NULL
, ginsn
->sym
);
1162 as_bad (_("SCFI: Invalid DWARF CFI opcode data"));
1166 /* Emit Synthesized DWARF CFI. */
1169 scfi_emit_dw2cfi (const symbolS
*func
)
1171 struct frch_ginsn_data
*frch_gdata
;
1172 ginsnS
* ginsn
= NULL
;
1174 frch_gdata
= frchain_now
->frch_ginsn_data
;
1175 ginsn
= frch_gdata
->gins_rootP
;
1179 switch (ginsn
->type
)
1181 case GINSN_TYPE_SYMBOL
:
1182 /* .cfi_startproc and .cfi_endproc pseudo-ops. */
1183 if (GINSN_F_FUNC_BEGIN_P (ginsn
))
1185 scfi_dot_cfi_startproc (frch_gdata
->start_addr
);
1188 else if (GINSN_F_FUNC_END_P (ginsn
))
1190 scfi_dot_cfi_endproc (ginsn
->sym
);
1194 case GINSN_TYPE_ADD
:
1195 case GINSN_TYPE_AND
:
1196 case GINSN_TYPE_CALL
:
1197 case GINSN_TYPE_JUMP
:
1198 case GINSN_TYPE_JUMP_COND
:
1199 case GINSN_TYPE_MOV
:
1200 case GINSN_TYPE_LOAD
:
1201 case GINSN_TYPE_PHANTOM
:
1202 case GINSN_TYPE_STORE
:
1203 case GINSN_TYPE_SUB
:
1204 case GINSN_TYPE_OTHER
:
1205 case GINSN_TYPE_RETURN
:
1207 /* For all other SCFI ops, invoke the handler. */
1208 if (ginsn
->scfi_ops
)
1209 handle_scfi_dot_cfi (ginsn
);
1213 /* No other GINSN_TYPE_* expected. */
1214 as_bad (_("SCFI: bad ginsn for func '%s'"),
1218 ginsn
= ginsn
->next
;
1226 scfi_emit_dw2cfi (const symbolS
*func ATTRIBUTE_UNUSED
)
1228 as_bad (_("SCFI: unsupported for target"));
1233 scfi_synthesize_dw2cfi (const symbolS
*func ATTRIBUTE_UNUSED
,
1234 gcfgS
*gcfg ATTRIBUTE_UNUSED
,
1235 gbbS
*root_bb ATTRIBUTE_UNUSED
)
1237 as_bad (_("SCFI: unsupported for target"));
1241 #endif /* defined (TARGET_USE_SCFI) && defined (TARGET_USE_GINSN). */