xref: /netbsd-src/external/gpl3/binutils/dist/gas/scfi.c (revision cb63e24e8d6aae7ddac1859a9015f48b1d8bd90e)
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 
40 enum 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 
53 struct 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 
63 typedef struct cfi_regloc cfi_reglocS;
64 
65 struct scfi_op_data
66 {
67   const char *name;
68 };
69 
70 typedef 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 
78 struct 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 
105 struct 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 
120 static scfi_opS *
init_scfi_op(void)121 init_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 
130 void
scfi_ops_cleanup(scfi_opS ** head)131 scfi_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 
152 static int
cmp_scfi_state(scfi_stateS * state1,scfi_stateS * state2)153 cmp_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
179 static void
180 scfi_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 
197 static void
scfi_state_save_reg(scfi_stateS * state,unsigned int reg,unsigned int base,offsetT offset)198 scfi_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 
211 static void
scfi_state_restore_reg(scfi_stateS * state,unsigned int reg)212 scfi_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 
231 static bool
ginsn_scfi_save_reg_p(ginsnS * ginsn,scfi_stateS * state)232 ginsn_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 
266 static bool
ginsn_scfi_restore_reg_p(ginsnS * ginsn,scfi_stateS * state)267 ginsn_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 
298 static int
ginsn_append_scfi_op(ginsnS * ginsn,scfi_opS * op)299 ginsn_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 
326 static void
scfi_op_add_def_cfa_reg(scfi_stateS * state,ginsnS * ginsn,unsigned int reg)327 scfi_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 
342 static void
scfi_op_add_cfa_offset_inc(scfi_stateS * state,ginsnS * ginsn,offsetT num)343 scfi_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 
358 static void
scfi_op_add_cfa_offset_dec(scfi_stateS * state,ginsnS * ginsn,offsetT num)359 scfi_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 
374 static void
scfi_op_add_def_cfa(scfi_stateS * state,ginsnS * ginsn,unsigned int reg,offsetT num)375 scfi_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 
392 static void
scfi_op_add_cfi_offset(scfi_stateS * state,ginsnS * ginsn,unsigned int reg)393 scfi_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 
406 static void
scfi_op_add_cfa_restore(ginsnS * ginsn,unsigned int reg)407 scfi_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 
421 static void
scfi_op_add_cfi_remember_state(ginsnS * ginsn)422 scfi_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 
433 static void
scfi_op_add_cfi_restore_state(ginsnS * ginsn)434 scfi_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 
446 void
scfi_op_add_cfi_label(ginsnS * ginsn,const char * name)447 scfi_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 
459 void
scfi_op_add_signal_frame(ginsnS * ginsn)460 scfi_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 
470 static int
verify_heuristic_traceable_reg_fp(ginsnS * ginsn,scfi_stateS * state)471 verify_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 
528 static int
verify_heuristic_traceable_stack_manipulation(ginsnS * ginsn,scfi_stateS * state)529 verify_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 
634 static int
verify_heuristic_symmetrical_restore_reg(scfi_stateS * state,ginsnS * ginsn)635 verify_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 
695 static int
gen_scfi_ops(ginsnS * ginsn,scfi_stateS * state)696 gen_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 
922 static int
forward_flow_scfi_state(gcfgS * gcfg,gbbS * gbb,scfi_stateS * state)923 forward_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 
987 fail:
988 
989   if (gedge)
990     gedge->visited = true;
991   return 1;
992 }
993 
994 static int
backward_flow_scfi_state(const symbolS * func ATTRIBUTE_UNUSED,gcfgS * gcfg)995 backward_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 
1066 int
scfi_synthesize_dw2cfi(const symbolS * func,gcfgS * gcfg,gbbS * root_bb)1067 scfi_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 
1091 end:
1092   free (init_state);
1093   return ret;
1094 }
1095 
1096 static int
handle_scfi_dot_cfi(ginsnS * ginsn)1097 handle_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;
1152 bad:
1153   as_bad (_("SCFI: Invalid DWARF CFI opcode data"));
1154   return 1;
1155 }
1156 
1157 /* Emit Synthesized DWARF CFI.  */
1158 
1159 int
scfi_emit_dw2cfi(const symbolS * func)1160 scfi_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 
1216 int
scfi_emit_dw2cfi(const symbolS * func ATTRIBUTE_UNUSED)1217 scfi_emit_dw2cfi (const symbolS *func ATTRIBUTE_UNUSED)
1218 {
1219   as_bad (_("SCFI: unsupported for target"));
1220   return 1;
1221 }
1222 
1223 int
scfi_synthesize_dw2cfi(const symbolS * func ATTRIBUTE_UNUSED,gcfgS * gcfg ATTRIBUTE_UNUSED,gbbS * root_bb ATTRIBUTE_UNUSED)1224 scfi_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