Updated Bulgarian translation for the binutils/ directory
[binutils-gdb.git] / gas / scfi.c
blob5898a57b3306d2a1bb4a6da25948d4890975f565
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->op_data);
145 free (op);
146 op = next;
147 next = op ? op->next : NULL;
150 free (head);
153 /* Compare two SCFI states. */
155 static int
156 cmp_scfi_state (scfi_stateS *state1, scfi_stateS *state2)
158 int ret;
160 if (!state1 || !state2)
161 return 1;
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;
180 return ret;
183 #if 0
184 static void
185 scfi_state_update_reg (scfi_stateS *state, uint32_t dst, uint32_t base,
186 int32_t offset)
188 if (dst >= MAX_NUM_SCFI_REGS)
189 return;
191 state->regs[dst].base = base;
192 state->regs[dst].offset = offset;
194 #endif
196 /* Update the SCFI state of REG as available on execution stack at OFFSET
197 from REG_CFA (BASE).
199 Note that BASE must be REG_CFA, because any other base (REG_SP, REG_FP)
200 is by definition transitory in the function. */
202 static void
203 scfi_state_save_reg (scfi_stateS *state, unsigned int reg, unsigned int base,
204 offsetT offset)
206 if (reg >= MAX_NUM_SCFI_REGS)
207 return;
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;
216 static void
217 scfi_state_restore_reg (scfi_stateS *state, unsigned int reg)
219 if (reg >= MAX_NUM_SCFI_REGS)
220 return;
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. */
237 static bool
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
248 register save. */
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)
251 return save_reg_p;
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)))
259 save_reg_p = true;
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)
264 save_reg_p = true;
266 return save_reg_p;
269 /* Identify if the given GAS instruction GINSN restores a register
270 (of interest) on stack. */
272 static bool
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
302 given GINSN. */
304 static int
305 ginsn_append_scfi_op (ginsnS *ginsn, scfi_opS *op)
307 scfi_opS *sop;
309 if (!ginsn || !op)
310 return 1;
312 if (!ginsn->scfi_ops)
314 ginsn->scfi_ops = XCNEW (scfi_opS *);
315 *ginsn->scfi_ops = op;
317 else
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;
322 while (sop->next)
323 sop = sop->next;
325 sop->next = op;
327 ginsn->num_scfi_ops++;
329 return 0;
332 static void
333 scfi_op_add_def_cfa_reg (scfi_stateS *state, ginsnS *ginsn, unsigned int reg)
335 scfi_opS *op = NULL;
337 state->regs[REG_CFA].base = reg;
339 op = init_scfi_op ();
341 op->dw2cfi_op = DW_CFA_def_cfa_register;
342 op->reg = REG_CFA;
343 op->loc = state->regs[REG_CFA];
345 ginsn_append_scfi_op (ginsn, op);
348 static void
349 scfi_op_add_cfa_offset_inc (scfi_stateS *state, ginsnS *ginsn, offsetT num)
351 scfi_opS *op = NULL;
353 state->regs[REG_CFA].offset -= num;
355 op = init_scfi_op ();
357 op->dw2cfi_op = DW_CFA_def_cfa_offset;
358 op->reg = REG_CFA;
359 op->loc = state->regs[REG_CFA];
361 ginsn_append_scfi_op (ginsn, op);
364 static void
365 scfi_op_add_cfa_offset_dec (scfi_stateS *state, ginsnS *ginsn, offsetT num)
367 scfi_opS *op = NULL;
369 state->regs[REG_CFA].offset += num;
371 op = init_scfi_op ();
373 op->dw2cfi_op = DW_CFA_def_cfa_offset;
374 op->reg = REG_CFA;
375 op->loc = state->regs[REG_CFA];
377 ginsn_append_scfi_op (ginsn, op);
380 static void
381 scfi_op_add_def_cfa (scfi_stateS *state, ginsnS *ginsn, unsigned int reg,
382 offsetT num)
384 scfi_opS *op = NULL;
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;
392 op->reg = REG_CFA;
393 op->loc = state->regs[REG_CFA];
395 ginsn_append_scfi_op (ginsn, op);
398 static void
399 scfi_op_add_cfi_offset (scfi_stateS *state, ginsnS *ginsn, unsigned int reg)
401 scfi_opS *op = NULL;
403 op = init_scfi_op ();
405 op->dw2cfi_op = DW_CFA_offset;
406 op->reg = reg;
407 op->loc = state->regs[reg];
409 ginsn_append_scfi_op (ginsn, op);
412 static void
413 scfi_op_add_cfa_restore (ginsnS *ginsn, unsigned int reg)
415 scfi_opS *op = NULL;
417 op = init_scfi_op ();
419 op->dw2cfi_op = DW_CFA_restore;
420 op->reg = reg;
421 op->loc.base = REG_INVALID;
422 op->loc.offset = 0;
424 ginsn_append_scfi_op (ginsn, op);
427 static void
428 scfi_op_add_cfi_remember_state (ginsnS *ginsn)
430 scfi_opS *op = NULL;
432 op = init_scfi_op ();
434 op->dw2cfi_op = DW_CFA_remember_state;
436 ginsn_append_scfi_op (ginsn, op);
439 static void
440 scfi_op_add_cfi_restore_state (ginsnS *ginsn)
442 scfi_opS *op = NULL;
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);
452 void
453 scfi_op_add_cfi_label (ginsnS *ginsn, const char *name)
455 scfi_opS *op = NULL;
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);
465 void
466 scfi_op_add_signal_frame (ginsnS *ginsn)
468 scfi_opS *op = NULL;
470 op = init_scfi_op ();
471 op->dw2cfi_op = CFI_signal_frame;
473 ginsn_append_scfi_op (ginsn, op);
476 static int
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
491 the prologue.
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)
507 fp_traceable_p = 0;
508 /* REG_FP restore is OK too. */
509 else if (ginsn->type == GINSN_TYPE_LOAD)
510 fp_traceable_p = 0;
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))
515 fp_traceable_p = 0;
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)
520 fp_traceable_p = 0;
521 /* All other ginsns with REG_FP as destination make REG_FP not
522 traceable. */
523 else
524 fp_traceable_p = 1;
527 if (fp_traceable_p)
528 as_bad_where (ginsn->file, ginsn->line,
529 _("SCFI: usage of REG_FP as scratch not supported"));
531 return fp_traceable_p;
534 static int
535 verify_heuristic_traceable_stack_manipulation (ginsnS *ginsn,
536 scfi_stateS *state)
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
551 allocation.
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
556 REG_FP.
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
560 all times. */
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;
640 static int
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;
647 unsigned int reg;
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.
651 E.g.,
652 push reg1
653 push reg2
655 body of func which uses reg1 , reg2 as scratch,
656 and may be even spills them to stack.
658 pop reg2
659 pop reg1
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
664 restore. */
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))
671 return sym_restore;
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)
687 ? -state->stack_size
688 : state->regs[REG_FP].offset)
689 + ginsn_get_src_disp (src1));
692 sym_restore = (expected_offset == state->regs[reg].offset);
694 return sym_restore;
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. */
701 static int
702 gen_scfi_ops (ginsnS *ginsn, scfi_stateS *state)
704 int ret = 0;
705 offsetT offset;
706 struct ginsn_src *src1;
707 struct ginsn_src *src2;
708 struct ginsn_dst *dst;
710 if (!ginsn || !state)
711 ret = 1;
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
715 target-specific. */
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;
720 return ret;
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);
728 if (ret)
729 return ret;
731 ret = verify_heuristic_traceable_reg_fp (ginsn, state);
732 if (ret)
733 return ret;
735 switch (ginsn->dst.type)
737 case GINSN_DST_REG:
738 switch (ginsn->type)
740 case GINSN_TYPE_MOV:
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));
771 else
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
783 intentional. */
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;
799 # if 0
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);
803 #endif
806 break;
807 case GINSN_TYPE_SUB:
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)
816 /* push reg. */
817 scfi_op_add_cfa_offset_dec (state, ginsn, ginsn_get_src_imm (src2));
820 break;
821 case GINSN_TYPE_ADD:
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));
842 break;
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));
866 else
867 as_warn_where (ginsn->file, ginsn->line,
868 _("SCFI: asymetrical register restore"));
871 break;
872 default:
873 break;
875 break;
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)
885 break;
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));
909 break;
911 default:
912 /* Skip GINSN_DST_UNKNOWN and GINSN_DST_MEM as they are uninteresting
913 currently for SCFI. */
914 break;
917 return ret;
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. */
928 static int
929 forward_flow_scfi_state (gcfgS *gcfg, gbbS *gbb, scfi_stateS *state)
931 ginsnS *ginsn;
932 gbbS *prev_bb;
933 gedgeS *gedge = NULL;
934 int ret = 0;
936 if (gbb->visited)
938 /* Check that the SCFI state is the same as previous. */
939 ret = cmp_scfi_state (state, gbb->entry_state);
940 if (ret)
941 as_bad (_("SCFI: Bad CFI propagation perhaps"));
942 return ret;
945 gbb->visited = true;
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);
955 if (ret)
956 goto fail;
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. */
964 prev_bb = gbb;
965 if (gbb->num_out_gedges)
967 bb_for_each_edge(gbb, gedge)
969 gbb = gedge->dst_bb;
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));
972 if (gbb->visited)
974 ret = cmp_scfi_state (gbb->entry_state, state);
975 if (ret)
976 goto fail;
979 if (!gedge->visited)
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);
987 if (ret)
988 goto fail;
993 return 0;
995 fail:
997 if (gedge)
998 gedge->visited = true;
999 return 1;
1002 static int
1003 backward_flow_scfi_state (const symbolS *func ATTRIBUTE_UNUSED, gcfgS *gcfg)
1005 gbbS **prog_order_bbs;
1006 gbbS **restore_bbs;
1007 gbbS *current_bb;
1008 gbbS *prev_bb;
1009 gbbS *dst_bb;
1010 ginsnS *ginsn;
1011 gedgeS *gedge = NULL;
1013 int ret = 0;
1014 uint64_t i, j;
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. */
1025 while (i > 0)
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
1035 later. */
1036 restore_bbs[i] = current_bb;
1038 else
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;
1050 break;
1054 i--;
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)
1062 ret = 1;
1063 break;
1066 free (restore_bbs);
1067 free (prog_order_bbs);
1069 return ret;
1072 /* Synthesize DWARF CFI for a function. */
1075 scfi_synthesize_dw2cfi (const symbolS *func, gcfgS *gcfg, gbbS *root_bb)
1077 int ret;
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);
1086 if (ret)
1088 as_bad (_("SCFI: forward pass failed for func '%s'"), S_GET_NAME (func));
1089 goto end;
1092 ret = backward_flow_scfi_state (func, gcfg);
1093 if (ret)
1095 as_bad (_("SCFI: backward pass failed for func '%s'"), S_GET_NAME (func));
1096 goto end;
1099 end:
1100 free (init_state);
1101 return ret;
1104 static int
1105 handle_scfi_dot_cfi (ginsnS *ginsn)
1107 scfi_opS *op;
1109 /* Nothing to do. */
1110 if (!ginsn->scfi_ops)
1111 return 0;
1113 op = *ginsn->scfi_ops;
1114 if (!op)
1115 goto bad;
1117 while (op)
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,
1123 ginsn->sym);
1124 break;
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);
1128 break;
1129 case DW_CFA_def_cfa:
1130 scfi_dot_cfi (DW_CFA_def_cfa, op->loc.base, 0, op->loc.offset,
1131 NULL, ginsn->sym);
1132 break;
1133 case DW_CFA_offset:
1134 scfi_dot_cfi (DW_CFA_offset, op->reg, 0, op->loc.offset, NULL,
1135 ginsn->sym);
1136 break;
1137 case DW_CFA_restore:
1138 scfi_dot_cfi (DW_CFA_restore, op->reg, 0, 0, NULL, ginsn->sym);
1139 break;
1140 case DW_CFA_remember_state:
1141 scfi_dot_cfi (DW_CFA_remember_state, 0, 0, 0, NULL, ginsn->sym);
1142 break;
1143 case DW_CFA_restore_state:
1144 scfi_dot_cfi (DW_CFA_restore_state, 0, 0, 0, NULL, ginsn->sym);
1145 break;
1146 case CFI_label:
1147 scfi_dot_cfi (CFI_label, 0, 0, 0, op->op_data->name, ginsn->sym);
1148 free ((char *) op->op_data->name);
1149 break;
1150 case CFI_signal_frame:
1151 scfi_dot_cfi (CFI_signal_frame, 0, 0, 0, NULL, ginsn->sym);
1152 break;
1153 default:
1154 goto bad;
1155 break;
1157 op = op->next;
1160 return 0;
1161 bad:
1162 as_bad (_("SCFI: Invalid DWARF CFI opcode data"));
1163 return 1;
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;
1177 while (ginsn)
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);
1186 break;
1188 else if (GINSN_F_FUNC_END_P (ginsn))
1190 scfi_dot_cfi_endproc (ginsn->sym);
1191 break;
1193 /* Fall through. */
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);
1210 break;
1212 default:
1213 /* No other GINSN_TYPE_* expected. */
1214 as_bad (_("SCFI: bad ginsn for func '%s'"),
1215 S_GET_NAME (func));
1216 break;
1218 ginsn = ginsn->next;
1220 return 0;
1223 #else
1226 scfi_emit_dw2cfi (const symbolS *func ATTRIBUTE_UNUSED)
1228 as_bad (_("SCFI: unsupported for target"));
1229 return 1;
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"));
1238 return 1;
1241 #endif /* defined (TARGET_USE_SCFI) && defined (TARGET_USE_GINSN). */