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
)
146 next
= op
? op
->next
: NULL
;
150 /* Compare two SCFI states. */
153 cmp_scfi_state (scfi_stateS
*state1
, scfi_stateS
*state2
)
157 if (!state1
|| !state2
)
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
;
180 scfi_state_update_reg (scfi_stateS
*state
, uint32_t dst
, uint32_t base
,
183 if (dst
>= MAX_NUM_SCFI_REGS
)
186 state
->regs
[dst
].base
= base
;
187 state
->regs
[dst
].offset
= offset
;
191 /* Update the SCFI state of REG as available on execution stack at OFFSET
194 Note that BASE must be REG_CFA, because any other base (REG_SP, REG_FP)
195 is by definition transitory in the function. */
198 scfi_state_save_reg (scfi_stateS
*state
, unsigned int reg
, unsigned int base
,
201 if (reg
>= MAX_NUM_SCFI_REGS
)
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
;
212 scfi_state_restore_reg (scfi_stateS
*state
, unsigned int reg
)
214 if (reg
>= MAX_NUM_SCFI_REGS
)
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. */
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
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
)
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
)))
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
)
263 /* Identify if the given GAS instruction GINSN restores a register
264 (of interest) on stack. */
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
299 ginsn_append_scfi_op (ginsnS
*ginsn
, scfi_opS
*op
)
306 if (!ginsn
->scfi_ops
)
308 ginsn
->scfi_ops
= XCNEW (scfi_opS
*);
309 *ginsn
->scfi_ops
= op
;
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
;
321 ginsn
->num_scfi_ops
++;
327 scfi_op_add_def_cfa_reg (scfi_stateS
*state
, ginsnS
*ginsn
, unsigned int reg
)
331 state
->regs
[REG_CFA
].base
= reg
;
333 op
= init_scfi_op ();
335 op
->dw2cfi_op
= DW_CFA_def_cfa_register
;
337 op
->loc
= state
->regs
[REG_CFA
];
339 ginsn_append_scfi_op (ginsn
, op
);
343 scfi_op_add_cfa_offset_inc (scfi_stateS
*state
, ginsnS
*ginsn
, offsetT num
)
347 state
->regs
[REG_CFA
].offset
-= num
;
349 op
= init_scfi_op ();
351 op
->dw2cfi_op
= DW_CFA_def_cfa_offset
;
353 op
->loc
= state
->regs
[REG_CFA
];
355 ginsn_append_scfi_op (ginsn
, op
);
359 scfi_op_add_cfa_offset_dec (scfi_stateS
*state
, ginsnS
*ginsn
, offsetT num
)
363 state
->regs
[REG_CFA
].offset
+= num
;
365 op
= init_scfi_op ();
367 op
->dw2cfi_op
= DW_CFA_def_cfa_offset
;
369 op
->loc
= state
->regs
[REG_CFA
];
371 ginsn_append_scfi_op (ginsn
, op
);
375 scfi_op_add_def_cfa (scfi_stateS
*state
, ginsnS
*ginsn
, unsigned int reg
,
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
;
387 op
->loc
= state
->regs
[REG_CFA
];
389 ginsn_append_scfi_op (ginsn
, op
);
393 scfi_op_add_cfi_offset (scfi_stateS
*state
, ginsnS
*ginsn
, unsigned int reg
)
397 op
= init_scfi_op ();
399 op
->dw2cfi_op
= DW_CFA_offset
;
401 op
->loc
= state
->regs
[reg
];
403 ginsn_append_scfi_op (ginsn
, op
);
407 scfi_op_add_cfa_restore (ginsnS
*ginsn
, unsigned int reg
)
411 op
= init_scfi_op ();
413 op
->dw2cfi_op
= DW_CFA_restore
;
415 op
->loc
.base
= REG_INVALID
;
418 ginsn_append_scfi_op (ginsn
, op
);
422 scfi_op_add_cfi_remember_state (ginsnS
*ginsn
)
426 op
= init_scfi_op ();
428 op
->dw2cfi_op
= DW_CFA_remember_state
;
430 ginsn_append_scfi_op (ginsn
, op
);
434 scfi_op_add_cfi_restore_state (ginsnS
*ginsn
)
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
);
447 scfi_op_add_cfi_label (ginsnS
*ginsn
, const char *name
)
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
);
460 scfi_op_add_signal_frame (ginsnS
*ginsn
)
464 op
= init_scfi_op ();
465 op
->dw2cfi_op
= CFI_signal_frame
;
467 ginsn_append_scfi_op (ginsn
, op
);
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
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
)
502 /* REG_FP restore is OK too. */
503 else if (ginsn
->type
== GINSN_TYPE_LOAD
)
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
))
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
)
515 /* All other ginsns with REG_FP as destination make REG_FP not
522 as_bad_where (ginsn
->file
, ginsn
->line
,
523 _("SCFI: usage of REG_FP as scratch not supported"));
525 return fp_traceable_p
;
529 verify_heuristic_traceable_stack_manipulation (ginsnS
*ginsn
,
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
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
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
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
;
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
;
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.
649 body of func which uses reg1 , reg2 as scratch,
650 and may be even spills them to stack.
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
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
))
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
)
682 : state
->regs
[REG_FP
].offset
)
683 + ginsn_get_src_disp (src1
));
686 sym_restore
= (expected_offset
== state
->regs
[reg
].offset
);
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. */
696 gen_scfi_ops (ginsnS
*ginsn
, scfi_stateS
*state
)
700 struct ginsn_src
*src1
;
701 struct ginsn_src
*src2
;
702 struct ginsn_dst
*dst
;
704 if (!ginsn
|| !state
)
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
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
;
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
);
725 ret
= verify_heuristic_traceable_reg_fp (ginsn
, state
);
729 switch (ginsn
->dst
.type
)
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
));
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
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;
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
);
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
)
811 scfi_op_add_cfa_offset_dec (state
, ginsn
, ginsn_get_src_imm (src2
));
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
));
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
));
861 as_warn_where (ginsn
->file
, ginsn
->line
,
862 _("SCFI: asymetrical register restore"));
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
)
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
));
906 /* Skip GINSN_DST_UNKNOWN and GINSN_DST_MEM as they are uninteresting
907 currently for SCFI. */
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. */
923 forward_flow_scfi_state (gcfgS
*gcfg
, gbbS
*gbb
, scfi_stateS
*state
)
927 gedgeS
*gedge
= NULL
;
932 /* Check that the SCFI state is the same as previous. */
933 ret
= cmp_scfi_state (state
, gbb
->entry_state
);
935 as_bad (_("SCFI: Bad CFI propagation perhaps"));
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
);
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. */
959 if (gbb
->num_out_gedges
)
961 bb_for_each_edge(gbb
, gedge
)
966 ret
= cmp_scfi_state (gbb
->entry_state
, state
);
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
);
990 gedge
->visited
= true;
995 backward_flow_scfi_state (const symbolS
*func ATTRIBUTE_UNUSED
, gcfgS
*gcfg
)
997 gbbS
**prog_order_bbs
;
1003 gedgeS
*gedge
= NULL
;
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. */
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
1028 restore_bbs
[i
] = current_bb
;
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
;
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
)
1059 free (prog_order_bbs
);
1064 /* Synthesize DWARF CFI for a function. */
1067 scfi_synthesize_dw2cfi (const symbolS
*func
, gcfgS
*gcfg
, gbbS
*root_bb
)
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
);
1080 as_bad (_("SCFI: forward pass failed for func '%s'"), S_GET_NAME (func
));
1084 ret
= backward_flow_scfi_state (func
, gcfg
);
1087 as_bad (_("SCFI: backward pass failed for func '%s'"), S_GET_NAME (func
));
1097 handle_scfi_dot_cfi (ginsnS
*ginsn
)
1101 /* Nothing to do. */
1102 if (!ginsn
->scfi_ops
)
1105 op
= *ginsn
->scfi_ops
;
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
,
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
);
1121 case DW_CFA_def_cfa
:
1122 scfi_dot_cfi (DW_CFA_def_cfa
, op
->loc
.base
, 0, op
->loc
.offset
,
1126 scfi_dot_cfi (DW_CFA_offset
, op
->reg
, 0, op
->loc
.offset
, NULL
,
1129 case DW_CFA_restore
:
1130 scfi_dot_cfi (DW_CFA_restore
, op
->reg
, 0, 0, NULL
, ginsn
->sym
);
1132 case DW_CFA_remember_state
:
1133 scfi_dot_cfi (DW_CFA_remember_state
, 0, 0, 0, NULL
, ginsn
->sym
);
1135 case DW_CFA_restore_state
:
1136 scfi_dot_cfi (DW_CFA_restore_state
, 0, 0, 0, NULL
, ginsn
->sym
);
1139 scfi_dot_cfi (CFI_label
, 0, 0, 0, op
->op_data
->name
, ginsn
->sym
);
1141 case CFI_signal_frame
:
1142 scfi_dot_cfi (CFI_signal_frame
, 0, 0, 0, NULL
, ginsn
->sym
);
1153 as_bad (_("SCFI: Invalid DWARF CFI opcode data"));
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
;
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
);
1179 else if (GINSN_F_FUNC_END_P (ginsn
))
1181 scfi_dot_cfi_endproc (ginsn
->sym
);
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
);
1204 /* No other GINSN_TYPE_* expected. */
1205 as_bad (_("SCFI: bad ginsn for func '%s'"),
1209 ginsn
= ginsn
->next
;
1217 scfi_emit_dw2cfi (const symbolS
*func ATTRIBUTE_UNUSED
)
1219 as_bad (_("SCFI: unsupported for target"));
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"));
1232 #endif /* defined (TARGET_USE_SCFI) && defined (TARGET_USE_GINSN). */