]> Git Repo - binutils.git/blob - gas/gen-sframe.c
Automatic date update in version.in
[binutils.git] / gas / gen-sframe.c
1 /* gen-sframe.c - Support for generating SFrame section.
2    Copyright (C) 2022 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 "subsegs.h"
23 #include "sframe.h"
24 #include "gen-sframe.h"
25 #include "dw2gencfi.h"
26
27 #ifdef support_sframe_p
28
29 /* By default, use 32-bit relocations from .sframe into .text.  */
30 #ifndef SFRAME_RELOC_SIZE
31 # define SFRAME_RELOC_SIZE 4
32 #endif
33
34 /* Whether frame row entries track RA.
35
36    A target may not need return address tracking for stack unwinding.  If it
37    does need the same, SFRAME_CFA_RA_REG must be defined with the return
38    address register number.  */
39
40 #if defined (sframe_ra_tracking_p) && defined (SFRAME_CFA_RA_REG)
41 # ifndef SFRAME_FRE_RA_TRACKING
42 # define SFRAME_FRE_RA_TRACKING 1
43 # endif
44 #endif
45
46 /* SFrame FRE type selection optimization is an optimization for size.
47
48    There are three flavors of SFrame FRE representation in the binary format:
49      - sframe_frame_row_entry_addr1 where the FRE start address is 1 byte.
50      - sframe_frame_row_entry_addr2 where the FRE start address is 2 bytes.
51      - sframe_frame_row_entry_addr4 where the FRE start address is 4 bytes.
52
53    Note that in the SFrame format, all SFrame FREs of a function use one
54    single representation.  The SFrame FRE type itself is identified via the
55    information in the SFrame FDE function info.
56
57    Now, to select the minimum required one from the list above, one needs to
58    make a decision based on the size (in bytes) of the function.
59
60    As a result, for this optimization, some fragments (generated with a new
61    type rs_sframe) for the SFrame section are fixed up later.
62
63    This optimization (for size) is enabled by default.  */
64
65 #ifndef SFRAME_FRE_TYPE_SELECTION_OPT
66 # define SFRAME_FRE_TYPE_SELECTION_OPT 1
67 #endif
68
69 /* Emit a single byte into the current segment.  */
70
71 static inline void
72 out_one (int byte)
73 {
74   FRAG_APPEND_1_CHAR (byte);
75 }
76
77 /* Emit a two-byte word into the current segment.  */
78
79 static inline void
80 out_two (int data)
81 {
82   md_number_to_chars (frag_more (2), data, 2);
83 }
84
85 /* Emit a four byte word into the current segment.  */
86
87 static inline void
88 out_four (int data)
89 {
90   md_number_to_chars (frag_more (4), data, 4);
91 }
92
93 /* Get the start address symbol from the DWARF FDE.  */
94
95 static symbolS*
96 get_dw_fde_start_addrS (const struct fde_entry *dw_fde)
97 {
98   return dw_fde->start_address;
99 }
100
101 /* Get the start address symbol from the DWARF FDE.  */
102
103 static symbolS*
104 get_dw_fde_end_addrS (const struct fde_entry *dw_fde)
105 {
106   return dw_fde->end_address;
107 }
108
109 /* SFrame Frame Row Entry (FRE) related functions.  */
110
111 static void
112 sframe_fre_set_begin_addr (struct sframe_row_entry *fre, symbolS *beginS)
113 {
114   fre->pc_begin = beginS;
115 }
116
117 static void
118 sframe_fre_set_end_addr (struct sframe_row_entry *fre, symbolS *endS)
119 {
120   fre->pc_end = endS;
121 }
122
123 static void
124 sframe_fre_set_cfa_base_reg (struct sframe_row_entry *fre,
125                              unsigned int cfa_base_reg)
126 {
127   fre->cfa_base_reg = cfa_base_reg;
128   fre->merge_candidate = false;
129 }
130
131 static void
132 sframe_fre_set_cfa_offset (struct sframe_row_entry *fre,
133                            offsetT cfa_offset)
134 {
135   fre->cfa_offset = cfa_offset;
136   fre->merge_candidate = false;
137 }
138
139 #ifdef SFRAME_FRE_RA_TRACKING
140 static void
141 sframe_fre_set_ra_track (struct sframe_row_entry *fre, offsetT ra_offset)
142 {
143   fre->ra_loc = SFRAME_FRE_ELEM_LOC_STACK;
144   fre->ra_offset = ra_offset;
145   fre->merge_candidate = false;
146 }
147 #endif
148
149 static void
150 sframe_fre_set_bp_track (struct sframe_row_entry *fre, offsetT bp_offset)
151 {
152   fre->bp_loc = SFRAME_FRE_ELEM_LOC_STACK;
153   fre->bp_offset = bp_offset;
154   fre->merge_candidate = false;
155 }
156
157 /* All stack offset values within an FRE are uniformly encoded in the same
158    number of bytes.  The size of the stack offset values will, however, vary
159    across FREs.  */
160
161 #define VALUE_8BIT  0x7f
162 #define VALUE_16BIT 0x7fff
163 #define VALUE_32BIT 0x7fffffff
164 #define VALUE_64BIT 0x7fffffffffffffff
165
166 /* Given a signed offset, return the size in bytes needed to represent it.  */
167
168 static unsigned int
169 get_offset_size_in_bytes (offsetT value)
170 {
171   unsigned int size = 0;
172
173   if (value <= VALUE_8BIT && value >= (offsetT) -VALUE_8BIT)
174     size = 1;
175   else if (value <= VALUE_16BIT && value >= (offsetT) -VALUE_16BIT)
176     size = 2;
177   else if (value <= VALUE_32BIT && value >= (offsetT) -VALUE_32BIT)
178     size = 4;
179   else if ((sizeof (offsetT) > 4) && (value <= (offsetT) VALUE_64BIT
180                                       && value >= (offsetT) -VALUE_64BIT))
181     size = 8;
182
183   return size;
184 }
185
186 #define SFRAME_FRE_OFFSET_FUNC_MAP_INDEX_1B  0 /* SFRAME_FRE_OFFSET_1B.  */
187 #define SFRAME_FRE_OFFSET_FUNC_MAP_INDEX_2B  1 /* SFRAME_FRE_OFFSET_2B.  */
188 #define SFRAME_FRE_OFFSET_FUNC_MAP_INDEX_4B  2 /* SFRAME_FRE_OFFSET_4B.  */
189 #define SFRAME_FRE_OFFSET_FUNC_MAP_INDEX_8B  3 /* Not supported in SFrame.  */
190 #define SFRAME_FRE_OFFSET_FUNC_MAP_INDEX_MAX SFRAME_FRE_OFFSET_FUNC_MAP_INDEX_8B
191
192 /* Helper struct for mapping offset size to output functions.  */
193
194 struct sframe_fre_offset_func_map
195 {
196   unsigned int offset_size;
197   void (*out_func)(int);
198 };
199
200 /* Given an OFFSET_SIZE, return the size in bytes needed to represent it.  */
201
202 static unsigned int
203 sframe_fre_offset_func_map_index (unsigned int offset_size)
204 {
205   unsigned int idx = SFRAME_FRE_OFFSET_FUNC_MAP_INDEX_MAX;
206
207   switch (offset_size)
208     {
209       case SFRAME_FRE_OFFSET_1B:
210         idx = SFRAME_FRE_OFFSET_FUNC_MAP_INDEX_1B;
211         break;
212       case SFRAME_FRE_OFFSET_2B:
213         idx = SFRAME_FRE_OFFSET_FUNC_MAP_INDEX_2B;
214         break;
215       case SFRAME_FRE_OFFSET_4B:
216         idx = SFRAME_FRE_OFFSET_FUNC_MAP_INDEX_4B;
217         break;
218       default:
219         /* Not supported in SFrame.  */
220         break;
221     }
222
223   return idx;
224 }
225
226 /* Mapping from offset size to the output function to emit the value.  */
227
228 static const
229 struct sframe_fre_offset_func_map
230 fre_offset_func_map[SFRAME_FRE_OFFSET_FUNC_MAP_INDEX_MAX+1] =
231 {
232   { SFRAME_FRE_OFFSET_1B, out_one },
233   { SFRAME_FRE_OFFSET_2B, out_two },
234   { SFRAME_FRE_OFFSET_4B, out_four },
235   { -1, NULL } /* Not Supported in SFrame.  */
236 };
237
238 /* SFrame version specific operations access.  */
239
240 static struct sframe_version_ops sframe_ver_ops;
241
242 /* SFrame (SFRAME_VERSION_1) set FRE info.  */
243
244 static unsigned char
245 sframe_v1_set_fre_info (unsigned int base_reg, unsigned int num_offsets,
246                         unsigned int offset_size)
247 {
248   unsigned char fre_info;
249   fre_info = SFRAME_V1_FRE_INFO (base_reg, num_offsets, offset_size);
250   return fre_info;
251 }
252
253 /* SFrame (SFRAME_VERSION_1) set function info.  */
254 static unsigned char
255 sframe_v1_set_func_info (unsigned int fde_type, unsigned int fre_type)
256 {
257   unsigned char func_info;
258   func_info = SFRAME_V1_FUNC_INFO (fde_type, fre_type);
259   return func_info;
260 }
261
262 /* SFrame version specific operations setup.  */
263
264 static void
265 sframe_set_version (uint32_t sframe_version __attribute__((unused)))
266 {
267   sframe_ver_ops.format_version = SFRAME_VERSION_1;
268
269   sframe_ver_ops.set_fre_info = sframe_v1_set_fre_info;
270
271   sframe_ver_ops.set_func_info = sframe_v1_set_func_info;
272 }
273
274 /* SFrame set FRE info.  */
275
276 static unsigned char
277 sframe_set_fre_info (unsigned int base_reg, unsigned int num_offsets,
278                      unsigned int offset_size)
279 {
280   return sframe_ver_ops.set_fre_info (base_reg, num_offsets,
281                                          offset_size);
282 }
283
284 /* SFrame set func info. */
285
286 ATTRIBUTE_UNUSED static unsigned char
287 sframe_set_func_info (unsigned int fde_type, unsigned int fre_type)
288 {
289   return sframe_ver_ops.set_func_info (fde_type, fre_type);
290 }
291
292 /* Get the number of SFrame FDEs for the current file.  */
293
294 static unsigned int
295 get_num_sframe_fdes (void);
296
297 /* Get the number of SFrame frame row entries for the current file.  */
298
299 static unsigned int
300 get_num_sframe_fres (void);
301
302 /* Get CFA base register ID as represented in SFrame Frame Row Entry.  */
303
304 static unsigned int
305 get_fre_base_reg_id (struct sframe_row_entry *sframe_fre)
306 {
307   unsigned int cfi_insn_cfa_base_reg = sframe_fre->cfa_base_reg;
308   unsigned fre_base_reg = SFRAME_BASE_REG_SP;
309
310   if (cfi_insn_cfa_base_reg == SFRAME_CFA_FP_REG)
311     fre_base_reg = SFRAME_BASE_REG_FP;
312
313   /* Only one bit is reserved in SFRAME_VERSION_1.  */
314   gas_assert (fre_base_reg == SFRAME_BASE_REG_SP
315               || fre_base_reg == SFRAME_BASE_REG_FP);
316
317   return fre_base_reg;
318 }
319
320 /* Get number of offsets necessary for the SFrame Frame Row Entry.  */
321
322 static unsigned int
323 get_fre_num_offsets (struct sframe_row_entry *sframe_fre)
324 {
325   /* Atleast 1 must always be present (to recover CFA).  */
326   unsigned int fre_num_offsets = 1;
327
328   if (sframe_fre->bp_loc == SFRAME_FRE_ELEM_LOC_STACK)
329     fre_num_offsets++;
330 #ifdef SFRAME_FRE_RA_TRACKING
331   if (sframe_fre->ra_loc == SFRAME_FRE_ELEM_LOC_STACK)
332     fre_num_offsets++;
333 #endif
334   return fre_num_offsets;
335 }
336
337 /* Get the minimum necessary offset size (in bytes) for this
338    SFrame frame row entry.  */
339
340 static unsigned int
341 sframe_get_fre_offset_size (struct sframe_row_entry *sframe_fre)
342 {
343   unsigned int max_offset_size = 0;
344   unsigned int cfa_offset_size = 0;
345   unsigned int bp_offset_size = 0;
346   unsigned int ra_offset_size = 0;
347
348   unsigned int fre_offset_size = 0;
349
350   /* What size of offsets appear in this frame row entry.  */
351   cfa_offset_size = get_offset_size_in_bytes (sframe_fre->cfa_offset);
352   if (sframe_fre->bp_loc == SFRAME_FRE_ELEM_LOC_STACK)
353     bp_offset_size = get_offset_size_in_bytes (sframe_fre->bp_offset);
354 #ifdef SFRAME_FRE_RA_TRACKING
355   if (sframe_ra_tracking_p ()
356       && sframe_fre->ra_loc == SFRAME_FRE_ELEM_LOC_STACK)
357     ra_offset_size = get_offset_size_in_bytes (sframe_fre->ra_offset);
358 #endif
359
360   /* Get the maximum size needed to represent the offsets.  */
361   max_offset_size = cfa_offset_size;
362   if (bp_offset_size > max_offset_size)
363     max_offset_size = bp_offset_size;
364   if (ra_offset_size > max_offset_size)
365     max_offset_size = ra_offset_size;
366
367   gas_assert (max_offset_size);
368
369   switch (max_offset_size)
370     {
371     case 1:
372       fre_offset_size = SFRAME_FRE_OFFSET_1B;
373       break;
374     case 2:
375       fre_offset_size = SFRAME_FRE_OFFSET_2B;
376       break;
377     case 4:
378       fre_offset_size = SFRAME_FRE_OFFSET_4B;
379       break;
380     default:
381       /* Offset of size 8 bytes is not supported in SFrame format
382          version 1.  */
383       as_fatal (_("SFrame unsupported offset value\n"));
384       break;
385     }
386
387   return fre_offset_size;
388 }
389
390 #if SFRAME_FRE_TYPE_SELECTION_OPT
391
392 /* Create a composite exression CEXP (for SFrame FRE start address) such that:
393
394       exp = <val> OP_absent <width>, where,
395
396     - <val> and <width> are themselves expressionS.
397     - <val> stores the expression which when evaluated gives the value of the
398       start address offset of the FRE.
399     - <width> stores the expression when evaluated gives the number of bytes
400       needed to encode the start address offset of the FRE.
401
402    The use of OP_absent as the X_op_symbol helps identify this expression
403    later when fragments are fixed up.  */
404
405 static void
406 create_fre_start_addr_exp (expressionS *cexp, symbolS *fre_pc_begin,
407                            symbolS *fde_start_address,
408                            symbolS *fde_end_address)
409 {
410   expressionS val;
411   expressionS width;
412
413   /* val expression stores the FDE start address offset from the start PC
414      of function.  */
415   val.X_op = O_subtract;
416   val.X_add_symbol = fre_pc_begin;
417   val.X_op_symbol = fde_start_address;
418   val.X_add_number = 0;
419
420   /* width expressions stores the size of the function.  This is used later
421      to determine the number of bytes to be used to encode the FRE start
422      address of each FRE of the function.  */
423   width.X_op = O_subtract;
424   width.X_add_symbol = fde_end_address;
425   width.X_op_symbol = fde_start_address;
426   width.X_add_number = 0;
427
428   cexp->X_op = O_absent;
429   cexp->X_add_symbol = make_expr_symbol (&val);
430   cexp->X_op_symbol = make_expr_symbol (&width);
431   cexp->X_add_number = 0;
432 }
433
434 /* Create a composite exression CEXP (for SFrame FDE function info) such that:
435
436       exp = <rest_of_func_info> OP_modulus <width>, where,
437
438     - <rest_of_func_info> and <width> are themselves expressionS.
439     - <rest_of_func_info> stores a constant expression where X_add_number is
440     used to stash away the func_info.  The upper 4-bits of the func_info are copied
441     back to the resulting byte by the fragment fixup logic.
442     - <width> stores the expression when evaluated gives the size of the
443     funtion in number of bytes.
444
445    The use of OP_modulus as the X_op_symbol helps identify this expression
446    later when fragments are fixed up.  */
447
448 static void
449 create_func_info_exp (expressionS *cexp, symbolS *dw_fde_end_addrS,
450                       symbolS *dw_fde_start_addrS, uint8_t func_info)
451 {
452   expressionS width;
453   expressionS rest_of_func_info;
454
455   width.X_op = O_subtract;
456   width.X_add_symbol = dw_fde_end_addrS;
457   width.X_op_symbol = dw_fde_start_addrS;
458   width.X_add_number = 0;
459
460   rest_of_func_info.X_op = O_constant;
461   rest_of_func_info.X_add_number = func_info;
462
463   cexp->X_op = O_modulus;
464   cexp->X_add_symbol = make_expr_symbol (&rest_of_func_info);
465   cexp->X_op_symbol = make_expr_symbol (&width);
466   cexp->X_add_number = 0;
467 }
468
469 #endif
470
471 static void
472 output_sframe_row_entry (symbolS *fde_start_addr,
473                          symbolS *fde_end_addr,
474                          struct sframe_row_entry *sframe_fre)
475 {
476   unsigned char fre_info;
477   unsigned int fre_num_offsets;
478   unsigned int fre_offset_size;
479   unsigned int fre_base_reg;
480   expressionS exp;
481   unsigned int fre_addr_size;
482
483   unsigned int idx = 0;
484   unsigned int fre_write_offsets = 0;
485
486   fre_addr_size = 4; /* 4 bytes by default.   FIXME tie it to fre_type? */
487
488   /* SFrame FRE Start Address.  */
489 #if SFRAME_FRE_TYPE_SELECTION_OPT
490   create_fre_start_addr_exp (&exp, sframe_fre->pc_begin, fde_start_addr,
491                              fde_end_addr);
492   frag_grow (fre_addr_size);
493   frag_var (rs_sframe, fre_addr_size, 0, (relax_substateT) 0,
494             make_expr_symbol (&exp), 0, (char *) frag_now);
495 #else
496   gas_assert (fde_end_addr);
497   exp.X_op = O_subtract;
498   exp.X_add_symbol = sframe_fre->pc_begin; /* to.  */
499   exp.X_op_symbol = fde_start_addr; /* from.  */
500   exp.X_add_number = 0;
501   emit_expr (&exp, fre_addr_size);
502 #endif
503
504   /* Create the fre_info using the CFA base register, number of offsets and max
505      size of offset in this frame row entry.  */
506   fre_base_reg = get_fre_base_reg_id (sframe_fre);
507   fre_num_offsets = get_fre_num_offsets (sframe_fre);
508   fre_offset_size = sframe_get_fre_offset_size (sframe_fre);
509   fre_info = sframe_set_fre_info (fre_base_reg, fre_num_offsets,
510                                      fre_offset_size);
511   out_one (fre_info);
512
513   idx = sframe_fre_offset_func_map_index (fre_offset_size);
514   gas_assert (idx < SFRAME_FRE_OFFSET_FUNC_MAP_INDEX_MAX);
515
516   /* Write out the offsets in order - cfa, bp, ra.  */
517   fre_offset_func_map[idx].out_func (sframe_fre->cfa_offset);
518   fre_write_offsets++;
519
520 #ifdef SFRAME_FRE_RA_TRACKING
521   if (sframe_fre->ra_loc == SFRAME_FRE_ELEM_LOC_STACK)
522     {
523       fre_offset_func_map[idx].out_func (sframe_fre->ra_offset);
524       fre_write_offsets++;
525     }
526 #endif
527   if (sframe_fre->bp_loc == SFRAME_FRE_ELEM_LOC_STACK)
528     {
529       fre_offset_func_map[idx].out_func (sframe_fre->bp_offset);
530       fre_write_offsets++;
531     }
532
533   /* Check if the expected number offsets have been written out
534      in this FRE.  */
535   gas_assert (fre_write_offsets == fre_num_offsets);
536 }
537
538 static void
539 output_sframe_funcdesc (symbolS *start_of_fre_section,
540                         symbolS *fre_symbol,
541                         struct sframe_func_entry *sframe_fde)
542 {
543   expressionS exp;
544   unsigned int addr_size;
545   symbolS *dw_fde_start_addrS, *dw_fde_end_addrS;
546
547   addr_size = SFRAME_RELOC_SIZE;
548   dw_fde_start_addrS = get_dw_fde_start_addrS (sframe_fde->dw_fde);
549   dw_fde_end_addrS = get_dw_fde_end_addrS (sframe_fde->dw_fde);
550
551   /* Start address of the function.  */
552   exp.X_op = O_subtract;
553   exp.X_add_symbol = dw_fde_start_addrS; /* to location.  */
554   exp.X_op_symbol = symbol_temp_new_now (); /* from location.  */
555   exp.X_add_number = 0;
556   emit_expr (&exp, addr_size);
557
558   /* Size of the function in bytes.  */
559   exp.X_op = O_subtract;
560   exp.X_add_symbol = dw_fde_end_addrS;
561   exp.X_op_symbol = dw_fde_start_addrS;
562   exp.X_add_number = 0;
563   emit_expr (&exp, addr_size);
564
565   /* Offset to the first frame row entry.  */
566   exp.X_op = O_subtract;
567   exp.X_add_symbol = fre_symbol; /* Minuend.  */
568   exp.X_op_symbol = start_of_fre_section; /* Subtrahend.  */
569   exp.X_add_number = 0;
570   emit_expr (&exp, addr_size);
571
572   /* Number of FREs.  */
573   out_four (sframe_fde->num_fres);
574
575   /* SFrame FDE function info.  */
576   unsigned char func_info;
577   func_info = sframe_set_func_info (SFRAME_FDE_TYPE_PCINC,
578                                     SFRAME_FRE_TYPE_ADDR4);
579 #if SFRAME_FRE_TYPE_SELECTION_OPT
580   expressionS cexp;
581   create_func_info_exp (&cexp, dw_fde_end_addrS, dw_fde_start_addrS,
582                         func_info);
583   frag_grow (1); /* Size of func info is unsigned char.  */
584   frag_var (rs_sframe, 1, 0, (relax_substateT) 0,
585             make_expr_symbol (&cexp), 0, (char *) frag_now);
586 #else
587   out_one (func_info);
588 #endif
589 }
590
591 static void
592 output_sframe_internal (void)
593 {
594   expressionS exp;
595   unsigned int i = 0;
596
597   symbolS *end_of_frame_hdr;
598   symbolS *end_of_frame_section;
599   symbolS *start_of_func_desc_section;
600   symbolS *start_of_fre_section;
601   struct sframe_func_entry *sframe_fde;
602   struct sframe_row_entry *sframe_fre;
603   unsigned char abi_arch = 0;
604   int fixed_bp_offset = SFRAME_CFA_FIXED_FP_INVALID;
605   int fixed_ra_offset = SFRAME_CFA_FIXED_RA_INVALID;
606   unsigned int addr_size;
607
608   addr_size = SFRAME_RELOC_SIZE;
609
610   /* The function desciptor entries as dumped by the assembler are not
611      sorted on PCs.  */
612   unsigned char sframe_flags = 0;
613   sframe_flags |= !SFRAME_F_FDE_SORTED;
614
615   unsigned int num_fdes = get_num_sframe_fdes ();
616   unsigned int num_fres = get_num_sframe_fres ();
617   symbolS **fre_symbols = XNEWVEC (symbolS *, num_fres);
618   for (i = 0; i < num_fres; i++)
619     fre_symbols[i] = symbol_temp_make ();
620
621   end_of_frame_hdr = symbol_temp_make ();
622   start_of_fre_section = symbol_temp_make ();
623   start_of_func_desc_section = symbol_temp_make ();
624   end_of_frame_section = symbol_temp_make ();
625
626   /* Output the preamble of SFrame section.  */
627   out_two (SFRAME_MAGIC);
628   out_one (SFRAME_VERSION);
629   out_one (sframe_flags);
630   /* abi/arch.  */
631 #ifdef sframe_get_abi_arch
632   abi_arch = sframe_get_abi_arch ();
633 #endif
634   gas_assert (abi_arch);
635   out_one (abi_arch);
636
637   /* Offset for the BP register from CFA.  Neither of the AMD64 or AAPCS64
638      ABIs have a fixed offset for the BP register from the CFA.  This may be
639      useful in future (but not without additional support in the toolchain)
640      for specialized handling/encoding for cases where, for example,
641      -fno-omit-frame-pointer is used.  */
642   out_one (fixed_bp_offset);
643
644   /* Offset for the return address from CFA is fixed for some ABIs
645      (e.g., AMD64), output a zero otherwise.  */
646 #ifdef sframe_ra_tracking_p
647   if (!sframe_ra_tracking_p ())
648     fixed_ra_offset = sframe_cfa_ra_offset ();
649 #endif
650   out_one (fixed_ra_offset);
651
652   /* None of the AMD64, or AARCH64 ABIs need the auxilliary header.
653      When the need does arise to use this field, the appropriate backend
654      must provide this information.  */
655   out_one (0); /* Auxilliary SFrame header length.  */
656
657   out_four (num_fdes); /* Number of FDEs.  */
658   out_four (num_fres); /* Number of FREs.  */
659
660   /* FRE sub-section len.  */
661   exp.X_op = O_subtract;
662   exp.X_add_symbol = end_of_frame_section;
663   exp.X_op_symbol = start_of_fre_section;
664   exp.X_add_number = 0;
665   emit_expr (&exp, addr_size);
666
667   /* Offset of Function Index sub-section.  */
668   exp.X_op = O_subtract;
669   exp.X_add_symbol = end_of_frame_hdr;
670   exp.X_op_symbol = start_of_func_desc_section;
671   exp.X_add_number = 0;
672   emit_expr (&exp, addr_size);
673
674   /* Offset of FRE sub-section.  */
675   exp.X_op = O_subtract;
676   exp.X_add_symbol = start_of_fre_section;
677   exp.X_op_symbol = end_of_frame_hdr;
678   exp.X_add_number = 0;
679   emit_expr (&exp, addr_size);
680
681   symbol_set_value_now (end_of_frame_hdr);
682   symbol_set_value_now (start_of_func_desc_section);
683
684   /* Output the SFrame function descriptor entries.  */
685   i = 0;
686   for (sframe_fde = all_sframe_fdes; sframe_fde; sframe_fde = sframe_fde->next)
687     {
688       output_sframe_funcdesc (start_of_fre_section,
689                               fre_symbols[i], sframe_fde);
690       i += sframe_fde->num_fres;
691     }
692
693   symbol_set_value_now (start_of_fre_section);
694
695   /* Output the SFrame FREs.  */
696   i = 0;
697   sframe_fde = all_sframe_fdes;
698
699   for (sframe_fde = all_sframe_fdes; sframe_fde; sframe_fde = sframe_fde->next)
700     {
701       for (sframe_fre = sframe_fde->sframe_fres;
702            sframe_fre;
703            sframe_fre = sframe_fre->next)
704         {
705           symbol_set_value_now (fre_symbols[i]);
706           output_sframe_row_entry (get_dw_fde_start_addrS (sframe_fde->dw_fde),
707                                    get_dw_fde_end_addrS (sframe_fde->dw_fde),
708                                    sframe_fre);
709           i++;
710         }
711     }
712
713   symbol_set_value_now (end_of_frame_section);
714
715   gas_assert (i == num_fres);
716
717   free (fre_symbols);
718   fre_symbols = NULL;
719 }
720
721 /* List of SFrame FDE entries.  */
722
723 struct sframe_func_entry *all_sframe_fdes;
724
725 /* Tail of the list to add to.  */
726
727 static struct sframe_func_entry **last_sframe_fde = &all_sframe_fdes;
728
729 static unsigned int
730 get_num_sframe_fdes (void)
731 {
732   struct sframe_func_entry *sframe_fde;
733   unsigned int total_fdes = 0;
734
735   for (sframe_fde = all_sframe_fdes; sframe_fde ; sframe_fde = sframe_fde->next)
736     total_fdes++;
737
738   return total_fdes;
739 }
740
741 /* Get the total number of SFrame row entries across the FDEs.  */
742
743 static unsigned int
744 get_num_sframe_fres (void)
745 {
746   struct sframe_func_entry *sframe_fde;
747   unsigned int total_fres = 0;
748
749   for (sframe_fde = all_sframe_fdes; sframe_fde ; sframe_fde = sframe_fde->next)
750     total_fres += sframe_fde->num_fres;
751
752   return total_fres;
753 }
754
755 /* Allocate an SFrame FDE.  */
756
757 static struct sframe_func_entry*
758 sframe_fde_alloc (void)
759 {
760   struct sframe_func_entry *sframe_fde = XCNEW (struct sframe_func_entry);
761   return sframe_fde;
762 }
763
764 /* Link the SFrame FDE in.  */
765
766 static int
767 sframe_fde_link (struct sframe_func_entry *sframe_fde)
768 {
769   *last_sframe_fde = sframe_fde;
770   last_sframe_fde = &sframe_fde->next;
771
772   return 0;
773 }
774
775 /* Free up the SFrame FDE.  */
776
777 static void
778 sframe_fde_free (struct sframe_func_entry *sframe_fde)
779 {
780   XDELETE (sframe_fde);
781   sframe_fde = NULL;
782 }
783
784 /* SFrame translation context functions.  */
785
786 /* Allocate a new SFrame translation context.  */
787
788 static struct sframe_xlate_ctx*
789 sframe_xlate_ctx_alloc (void)
790 {
791   struct sframe_xlate_ctx* xlate_ctx = XCNEW (struct sframe_xlate_ctx);
792   return xlate_ctx;
793 }
794
795 /* Initialize the given SFrame translation context.  */
796
797 static void
798 sframe_xlate_ctx_init (struct sframe_xlate_ctx *xlate_ctx)
799 {
800   xlate_ctx->dw_fde = NULL;
801   xlate_ctx->first_fre = NULL;
802   xlate_ctx->last_fre = NULL;
803   xlate_ctx->cur_fre = NULL;
804   xlate_ctx->remember_fre = NULL;
805   xlate_ctx->num_xlate_fres = 0;
806 }
807
808 /* Cleanup the given SFrame translation context.  */
809
810 static void
811 sframe_xlate_ctx_cleanup (struct sframe_xlate_ctx *xlate_ctx)
812 {
813   struct sframe_row_entry *fre, *fre_next;
814
815   if (xlate_ctx->num_xlate_fres)
816     {
817       fre = xlate_ctx->first_fre;
818       while (fre)
819         {
820           fre_next = fre->next;
821           XDELETE (fre);
822           fre = fre_next;
823         }
824     }
825
826   sframe_xlate_ctx_init (xlate_ctx);
827 }
828
829 /* Transfer the state from the SFrame translation context to the SFrame FDE.  */
830
831 static void
832 sframe_xlate_ctx_finalize (struct sframe_xlate_ctx *xlate_ctx,
833                            struct sframe_func_entry *sframe_fde)
834 {
835   sframe_fde->dw_fde = xlate_ctx->dw_fde;
836   sframe_fde->sframe_fres = xlate_ctx->first_fre;
837   sframe_fde->num_fres = xlate_ctx->num_xlate_fres;
838 }
839
840 static struct sframe_row_entry*
841 sframe_row_entry_new (void)
842 {
843   struct sframe_row_entry *fre = XCNEW (struct sframe_row_entry);
844   /* Reset cfa_base_reg to -1.  A value of 0 will imply some valid register
845      for the supported arches.  */
846   fre->cfa_base_reg = -1;
847   fre->merge_candidate = true;
848
849   return fre;
850 }
851
852 /* Add the given FRE in the list of frame row entries in the given FDE
853    translation context.  */
854
855 static void
856 sframe_xlate_ctx_add_fre (struct sframe_xlate_ctx *xlate_ctx,
857                          struct sframe_row_entry *fre)
858 {
859   gas_assert (xlate_ctx && fre);
860
861   /* Add the frame row entry.  */
862   if (!xlate_ctx->first_fre)
863     xlate_ctx->first_fre = fre;
864   else if (xlate_ctx->last_fre)
865     xlate_ctx->last_fre->next = fre;
866
867   xlate_ctx->last_fre = fre;
868
869   /* Keep track of the total number of SFrame frame row entries.  */
870   xlate_ctx->num_xlate_fres++;
871 }
872
873 /* A SFrame Frame Row Entry is self-sufficient in terms of unwind information
874    for a given PC.  It contains information assimilated from multiple CFI
875    instructions, and hence, a new SFrame FRE is initialized with the data from
876    the previous known FRE, if any.
877
878    Understandably, not all information (especially the instruction begin
879    and end boundaries) needs to be relayed.  Hence, the caller of this API
880    must set the pc_begin and pc_end as applicable.  */
881
882 static void
883 sframe_row_entry_initialize (struct sframe_row_entry *cur_fre,
884                              struct sframe_row_entry *prev_fre)
885 {
886   gas_assert (prev_fre);
887   cur_fre->cfa_base_reg = prev_fre->cfa_base_reg;
888   cur_fre->cfa_offset = prev_fre->cfa_offset;
889   cur_fre->bp_loc = prev_fre->bp_loc;
890   cur_fre->bp_offset = prev_fre->bp_offset;
891   cur_fre->ra_loc = prev_fre->ra_loc;
892   cur_fre->ra_offset = prev_fre->ra_offset;
893 }
894
895 /* Translate DW_CFA_advance_loc into SFrame context.
896    Return SFRAME_XLATE_OK if success.  */
897
898 static int
899 sframe_xlate_do_advance_loc (struct sframe_xlate_ctx *xlate_ctx,
900                              struct cfi_insn_data *cfi_insn)
901 {
902   struct sframe_row_entry *last_fre = xlate_ctx->last_fre;
903   /* Get the scratchpad FRE currently being updated as the cfi_insn's
904      get interpreted.  This FRE eventually gets linked in into the
905      list of FREs for the specific function.  */
906   struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
907
908   if (cur_fre)
909     {
910       if (!cur_fre->merge_candidate)
911         {
912           sframe_fre_set_end_addr (cur_fre, cfi_insn->u.ll.lab2);
913
914           sframe_xlate_ctx_add_fre (xlate_ctx, cur_fre);
915           last_fre = xlate_ctx->last_fre;
916
917           xlate_ctx->cur_fre = sframe_row_entry_new ();
918           cur_fre = xlate_ctx->cur_fre;
919
920           if (last_fre)
921             sframe_row_entry_initialize (cur_fre, last_fre);
922         }
923       else
924         {
925           sframe_fre_set_end_addr (last_fre, cfi_insn->u.ll.lab2);
926           gas_assert (last_fre->merge_candidate == false);
927         }
928     }
929   else
930     {
931       xlate_ctx->cur_fre = sframe_row_entry_new ();
932       cur_fre = xlate_ctx->cur_fre;
933     }
934
935   gas_assert (cur_fre);
936   sframe_fre_set_begin_addr (cur_fre, cfi_insn->u.ll.lab2);
937
938   return SFRAME_XLATE_OK;
939 }
940
941 /* Translate DW_CFA_def_cfa into SFrame context.
942    Return SFRAME_XLATE_OK if success.  */
943
944 static int
945 sframe_xlate_do_def_cfa (struct sframe_xlate_ctx *xlate_ctx,
946                          struct cfi_insn_data *cfi_insn)
947
948 {
949   /* Get the scratchpad FRE.  This FRE will eventually get linked in.  */
950   struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
951   if (!cur_fre)
952   {
953     xlate_ctx->cur_fre = sframe_row_entry_new ();
954     cur_fre = xlate_ctx->cur_fre;
955     sframe_fre_set_begin_addr (cur_fre,
956                                get_dw_fde_start_addrS (xlate_ctx->dw_fde));
957   }
958   /* Define the current CFA rule to use the provided register and
959      offset.  */
960   sframe_fre_set_cfa_base_reg (cur_fre, cfi_insn->u.ri.reg);
961   sframe_fre_set_cfa_offset (cur_fre, cfi_insn->u.ri.offset);
962   cur_fre->merge_candidate = false;
963
964   return SFRAME_XLATE_OK;
965 }
966
967 /* Translate DW_CFA_def_cfa_register into SFrame context.
968    Return SFRAME_XLATE_OK if success.  */
969
970 static int
971 sframe_xlate_do_def_cfa_register (struct sframe_xlate_ctx *xlate_ctx,
972                                   struct cfi_insn_data *cfi_insn)
973 {
974   struct sframe_row_entry *last_fre = xlate_ctx->last_fre;
975   /* Get the scratchpad FRE.  This FRE will eventually get linked in.  */
976   struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
977   gas_assert (cur_fre);
978   /* Define the current CFA rule to use the provided register (but to
979      keep the old offset).  */
980   sframe_fre_set_cfa_base_reg (cur_fre, cfi_insn->u.ri.reg);
981   sframe_fre_set_cfa_offset (cur_fre, last_fre->cfa_offset);
982   cur_fre->merge_candidate = false;
983
984   return SFRAME_XLATE_OK;
985 }
986
987 /* Translate DW_CFA_def_cfa_offset into SFrame context.
988    Return SFRAME_XLATE_OK if success.  */
989
990 static int
991 sframe_xlate_do_def_cfa_offset (struct sframe_xlate_ctx *xlate_ctx,
992                                 struct cfi_insn_data *cfi_insn)
993 {
994   /* The scratchpad FRE currently being updated with each cfi_insn
995      being interpreted.  This FRE eventually gets linked in into the
996      list of FREs for the specific function.  */
997   struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
998
999   gas_assert (cur_fre);
1000   /*  Define the current CFA rule to use the provided offset (but to keep
1001       the old register).  However, if the old register is not FP/SP,
1002       skip creating SFrame unwind info for the function. */
1003   if ((cur_fre->cfa_base_reg == SFRAME_CFA_FP_REG)
1004       || (cur_fre->cfa_base_reg == SFRAME_CFA_SP_REG))
1005     {
1006       sframe_fre_set_cfa_offset (cur_fre, cfi_insn->u.i);
1007       cur_fre->merge_candidate = false;
1008     }
1009   else
1010     return SFRAME_XLATE_ERR_NOTREPRESENTED;
1011
1012   return SFRAME_XLATE_OK;
1013 }
1014
1015 /* Translate DW_CFA_offset into SFrame context.
1016    Return SFRAME_XLATE_OK if success.  */
1017
1018 static int
1019 sframe_xlate_do_offset (struct sframe_xlate_ctx *xlate_ctx,
1020                         struct cfi_insn_data *cfi_insn)
1021 {
1022   /* The scratchpad FRE currently being updated with each cfi_insn
1023      being interpreted.  This FRE eventually gets linked in into the
1024      list of FREs for the specific function.  */
1025   struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
1026
1027   gas_assert (cur_fre);
1028   /* Change the rule for the register indicated by the register number to
1029      be the specified offset.  */
1030   if (cfi_insn->u.r == SFRAME_CFA_FP_REG)
1031     {
1032       gas_assert (!cur_fre->base_reg);
1033       sframe_fre_set_bp_track (cur_fre, cfi_insn->u.ri.offset);
1034       cur_fre->merge_candidate = false;
1035     }
1036 #ifdef SFRAME_FRE_RA_TRACKING
1037   else if (sframe_ra_tracking_p ()
1038            && cfi_insn->u.r == SFRAME_CFA_RA_REG)
1039     {
1040       sframe_fre_set_ra_track (cur_fre, cfi_insn->u.ri.offset);
1041       cur_fre->merge_candidate = false;
1042     }
1043 #endif
1044   /* This is used to track changes to non-rsp registers, skip all others
1045      except FP / RA for now.  */
1046   return SFRAME_XLATE_OK;
1047 }
1048
1049 /* Translate DW_CFA_val_offset into SFrame context.
1050    Return SFRAME_XLATE_OK if success.  */
1051
1052 static int
1053 sframe_xlate_do_val_offset (struct sframe_xlate_ctx *xlate_ctx ATTRIBUTE_UNUSED,
1054                             struct cfi_insn_data *cfi_insn)
1055 {
1056   /* Previous value of register is CFA + offset.  However, if the specified
1057      register is not interesting (FP or RA reg), the current DW_CFA_val_offset
1058      instruction can be safely skipped without sacrificing the asynchonicity of
1059      unwind information.  */
1060   if (cfi_insn->u.r == SFRAME_CFA_FP_REG)
1061     return SFRAME_XLATE_ERR_NOTREPRESENTED; /* Not represented.  */
1062 #ifdef SFRAME_FRE_RA_TRACKING
1063   else if (sframe_ra_tracking_p ()
1064            && cfi_insn->u.r == SFRAME_CFA_RA_REG)
1065     return SFRAME_XLATE_ERR_NOTREPRESENTED; /* Not represented.  */
1066 #endif
1067
1068   /* Safe to skip.  */
1069   return SFRAME_XLATE_OK;
1070 }
1071
1072 /* Translate DW_CFA_remember_state into SFrame context.
1073    Return SFRAME_XLATE_OK if success.  */
1074
1075 static int
1076 sframe_xlate_do_remember_state (struct sframe_xlate_ctx *xlate_ctx)
1077 {
1078   struct sframe_row_entry *last_fre = xlate_ctx->last_fre;
1079
1080   /* If there is no FRE state to remember, nothing to do here.  Return
1081      early with non-zero error code, this will cause no SFrame unwind info
1082      for the function involved.  */
1083   if (!last_fre)
1084     return SFRAME_XLATE_ERR_INVAL;
1085
1086   if (!xlate_ctx->remember_fre)
1087     xlate_ctx->remember_fre = sframe_row_entry_new ();
1088   sframe_row_entry_initialize (xlate_ctx->remember_fre, last_fre);
1089
1090   return SFRAME_XLATE_OK;
1091 }
1092
1093 /* Translate DW_CFA_restore_state into SFrame context.
1094    Return SFRAME_XLATE_OK if success.  */
1095
1096 static int
1097 sframe_xlate_do_restore_state (struct sframe_xlate_ctx *xlate_ctx)
1098 {
1099   /* The scratchpad FRE currently being updated with each cfi_insn
1100      being interpreted.  This FRE eventually gets linked in into the
1101      list of FREs for the specific function.  */
1102   struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
1103
1104   gas_assert (xlate_ctx->remember_fre);
1105   gas_assert (cur_fre && cur_fre->merge_candidate);
1106
1107   /* Get the CFA state from the DW_CFA_remember_state insn.  */
1108   sframe_row_entry_initialize (cur_fre, xlate_ctx->remember_fre);
1109   /* The PC boundaries of the current SFrame FRE are updated
1110      via other machinery.  */
1111   cur_fre->merge_candidate = false;
1112   return SFRAME_XLATE_OK;
1113 }
1114
1115 /* Translate DW_CFA_restore into SFrame context.
1116    Return SFRAME_XLATE_OK if success.  */
1117
1118 static int
1119 sframe_xlate_do_restore (struct sframe_xlate_ctx *xlate_ctx,
1120                          struct cfi_insn_data *cfi_insn)
1121 {
1122   struct sframe_row_entry *cie_fre = xlate_ctx->first_fre;
1123   /* The scratchpad FRE currently being updated with each cfi_insn
1124      being interpreted.  This FRE eventually gets linked in into the
1125      list of FREs for the specific function.  */
1126   struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
1127
1128   /* Change the rule for the indicated register to the rule assigned to
1129      it by the initial_instructions in the CIE.  */
1130   gas_assert (cie_fre);
1131   /* SFrame FREs track only CFA and FP / RA for backtracing purposes;
1132      skip the other .cfi_restore directives.  */
1133   if (cfi_insn->u.r == SFRAME_CFA_FP_REG)
1134     {
1135       gas_assert (cur_fre);
1136       cur_fre->bp_loc = cie_fre->bp_loc;
1137       cur_fre->bp_offset = cie_fre->bp_offset;
1138       cur_fre->merge_candidate = false;
1139     }
1140 #ifdef SFRAME_FRE_RA_TRACKING
1141   else if (sframe_ra_tracking_p ()
1142            && cfi_insn->u.r == SFRAME_CFA_RA_REG)
1143     {
1144       gas_assert (cur_fre);
1145       cur_fre->ra_loc = cie_fre->ra_loc;
1146       cur_fre->ra_offset = cie_fre->ra_offset;
1147       cur_fre->merge_candidate = false;
1148     }
1149 #endif
1150   return SFRAME_XLATE_OK;
1151 }
1152
1153 /* Process CFI_INSN and update the translation context with the FRE
1154    information.
1155
1156    Returns an error code (sframe_xlate_err) if CFI_INSN is not successfully
1157    processed.  */
1158
1159 static int
1160 sframe_do_cfi_insn (struct sframe_xlate_ctx *xlate_ctx,
1161                     struct cfi_insn_data *cfi_insn)
1162 {
1163   int err = 0;
1164
1165   /* Atleast one cfi_insn per FDE is expected.  */
1166   gas_assert (cfi_insn);
1167   int op = cfi_insn->insn;
1168
1169   switch (op)
1170     {
1171     case DW_CFA_advance_loc:
1172       err = sframe_xlate_do_advance_loc (xlate_ctx, cfi_insn);
1173       break;
1174     case DW_CFA_def_cfa:
1175       err = sframe_xlate_do_def_cfa (xlate_ctx, cfi_insn);
1176       break;
1177     case DW_CFA_def_cfa_register:
1178       err = sframe_xlate_do_def_cfa_register (xlate_ctx, cfi_insn);
1179       break;
1180     case DW_CFA_def_cfa_offset:
1181       err = sframe_xlate_do_def_cfa_offset (xlate_ctx, cfi_insn);
1182       break;
1183     case DW_CFA_offset:
1184       err = sframe_xlate_do_offset (xlate_ctx, cfi_insn);
1185       break;
1186     case DW_CFA_val_offset:
1187       err = sframe_xlate_do_val_offset (xlate_ctx, cfi_insn);
1188       break;
1189     case DW_CFA_remember_state:
1190       err = sframe_xlate_do_remember_state (xlate_ctx);
1191       break;
1192     case DW_CFA_restore_state:
1193       err = sframe_xlate_do_restore_state (xlate_ctx);
1194       break;
1195     case DW_CFA_restore:
1196       err = sframe_xlate_do_restore (xlate_ctx, cfi_insn);
1197       break;
1198     case DW_CFA_undefined:
1199     case DW_CFA_same_value:
1200       break;
1201     default:
1202       {
1203         /* Other CFI opcodes are not processed at this time.
1204            These do not impact the coverage of the basic stack unwinding
1205            information as conveyed in the SFrame format.
1206             - DW_CFA_register,
1207             - ...
1208
1209            Following skipped operations do, however, impact the asynchronicity:
1210              - CFI_escape,
1211              - DW_CFA_GNU_window_save,
1212              - DW_CFA_AARCH64_negate_ra_state (multiplexed with
1213                DW_CFA_GNU_window_save)  */
1214
1215         err = SFRAME_XLATE_ERR_NOTREPRESENTED;
1216         // printf (_("SFrame Unsupported or unknown Dwarf CFI number: %#x\n"), op);
1217       }
1218     }
1219
1220   return err;
1221 }
1222
1223
1224 static int
1225 sframe_do_fde (struct sframe_xlate_ctx *xlate_ctx,
1226                const struct fde_entry *dw_fde)
1227 {
1228   struct cfi_insn_data *cfi_insn;
1229   int err = SFRAME_XLATE_OK;
1230
1231   xlate_ctx->dw_fde = dw_fde;
1232
1233   /* If the return column is not RIP, SFrame format cannot represent it.  */
1234   if (xlate_ctx->dw_fde->return_column != DWARF2_DEFAULT_RETURN_COLUMN)
1235     return SFRAME_XLATE_ERR_NOTREPRESENTED;
1236
1237   /* Iterate over the CFIs and create SFrame FREs.  */
1238   for (cfi_insn = dw_fde->data; cfi_insn; cfi_insn = cfi_insn->next)
1239     {
1240       /* Translate each CFI, and buffer the state in translation context.  */
1241       err = sframe_do_cfi_insn (xlate_ctx, cfi_insn);
1242       if (err != SFRAME_XLATE_OK)
1243         {
1244           /* Skip generating SFrame unwind info for the function if any
1245              offending CFI is encountered by sframe_do_cfi_insn ().  */
1246           return err; /* Return the error code.  */
1247         }
1248     }
1249
1250   /* No errors encountered.  */
1251
1252   /* Link in the scratchpad FRE that the last few CFI insns helped create.  */
1253   if (xlate_ctx->cur_fre)
1254     {
1255       sframe_xlate_ctx_add_fre (xlate_ctx, xlate_ctx->cur_fre);
1256       xlate_ctx->cur_fre = NULL;
1257     }
1258   /* Designate the end of the last SFrame FRE.  */
1259   if (xlate_ctx->last_fre)
1260     {
1261       xlate_ctx->last_fre->pc_end
1262         = get_dw_fde_end_addrS (xlate_ctx->dw_fde);
1263     }
1264
1265   return SFRAME_XLATE_OK;
1266 }
1267
1268 /* Create SFrame unwind info for all functions.
1269
1270    This function consumes the already generated FDEs (by dw2gencfi) and
1271    generates unwind data in SFrame format.  */
1272
1273 static void
1274 create_sframe_all (void)
1275 {
1276   struct fde_entry *dw_fde = NULL;
1277   struct sframe_func_entry *sframe_fde = NULL;
1278
1279   struct sframe_xlate_ctx *xlate_ctx = sframe_xlate_ctx_alloc ();
1280
1281   for (dw_fde = all_fde_data; dw_fde ; dw_fde = dw_fde->next)
1282     {
1283       sframe_fde = sframe_fde_alloc ();
1284       /* Initialize the translation context with information anew.  */
1285       sframe_xlate_ctx_init (xlate_ctx);
1286
1287       /* Process and link SFrame FDEs if no error.  Also skip adding an SFrame
1288          FDE if it does not contain any SFrame FREs.  There is little use of an
1289          SFrame FDE if there is no unwind information about the function.  */
1290       int err = sframe_do_fde (xlate_ctx, dw_fde);
1291       if (err || xlate_ctx->num_xlate_fres == 0)
1292         {
1293           sframe_xlate_ctx_cleanup (xlate_ctx);
1294           sframe_fde_free (sframe_fde);
1295         }
1296       else
1297         {
1298           /* All done.  Transfer the state from the SFrame translation
1299              context to the SFrame FDE.  */
1300           sframe_xlate_ctx_finalize (xlate_ctx, sframe_fde);
1301           sframe_fde_link (sframe_fde);
1302         }
1303     }
1304 }
1305
1306 void
1307 output_sframe (segT sframe_seg)
1308 {
1309   (void) sframe_seg;
1310
1311   /* Setup the version specific access functions.  */
1312   sframe_set_version (SFRAME_VERSION_1);
1313
1314   /* Process all fdes and create SFrame unwind information.  */
1315   create_sframe_all ();
1316
1317   output_sframe_internal ();
1318 }
1319
1320 #else  /*  support_sframe_p  */
1321
1322 void
1323 output_sframe (segT sframe_seg __attribute__((unused)))
1324 {
1325 }
1326
1327 #endif /*  support_sframe_p  */
This page took 0.097345 seconds and 4 git commands to generate.