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