1/* dw2gencfi.c - Support for generating Dwarf2 CFI information.
2   Copyright 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
3   Contributed by Michal Ludvig <mludvig@suse.cz>
4
5   This file is part of GAS, the GNU Assembler.
6
7   GAS is free software; you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation; either version 2, or (at your option)
10   any later version.
11
12   GAS is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with GAS; see the file COPYING.  If not, write to the Free
19   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
20   02110-1301, USA.  */
21
22#include "as.h"
23#include "dw2gencfi.h"
24
25
26/* We re-use DWARF2_LINE_MIN_INSN_LENGTH for the code alignment field
27   of the CIE.  Default to 1 if not otherwise specified.  */
28#ifndef  DWARF2_LINE_MIN_INSN_LENGTH
29# define DWARF2_LINE_MIN_INSN_LENGTH 1
30#endif
31
32/* If TARGET_USE_CFIPOP is defined, it is required that the target
33   provide the following definitions.  Otherwise provide them to
34   allow compilation to continue.  */
35#ifndef TARGET_USE_CFIPOP
36# ifndef  DWARF2_DEFAULT_RETURN_COLUMN
37#  define DWARF2_DEFAULT_RETURN_COLUMN 0
38# endif
39# ifndef  DWARF2_CIE_DATA_ALIGNMENT
40#  define DWARF2_CIE_DATA_ALIGNMENT 1
41# endif
42#endif
43
44#ifndef EH_FRAME_ALIGNMENT
45# define EH_FRAME_ALIGNMENT (bfd_get_arch_size (stdoutput) == 64 ? 3 : 2)
46#endif
47
48#ifndef tc_cfi_frame_initial_instructions
49# define tc_cfi_frame_initial_instructions() ((void)0)
50#endif
51
52
53struct cfi_insn_data
54{
55  struct cfi_insn_data *next;
56  int insn;
57  union {
58    struct {
59      unsigned reg;
60      offsetT offset;
61    } ri;
62
63    struct {
64      unsigned reg1;
65      unsigned reg2;
66    } rr;
67
68    unsigned r;
69    offsetT i;
70
71    struct {
72      symbolS *lab1;
73      symbolS *lab2;
74    } ll;
75
76    struct cfi_escape_data {
77      struct cfi_escape_data *next;
78      expressionS exp;
79    } *esc;
80  } u;
81};
82
83struct fde_entry
84{
85  struct fde_entry *next;
86  symbolS *start_address;
87  symbolS *end_address;
88  struct cfi_insn_data *data;
89  struct cfi_insn_data **last;
90  unsigned int return_column;
91  unsigned int signal_frame;
92};
93
94struct cie_entry
95{
96  struct cie_entry *next;
97  symbolS *start_address;
98  unsigned int return_column;
99  unsigned int signal_frame;
100  struct cfi_insn_data *first, *last;
101};
102
103
104/* Current open FDE entry.  */
105static struct fde_entry *cur_fde_data;
106static symbolS *last_address;
107static offsetT cur_cfa_offset;
108
109/* List of FDE entries.  */
110static struct fde_entry *all_fde_data;
111static struct fde_entry **last_fde_data = &all_fde_data;
112
113/* List of CIEs so that they could be reused.  */
114static struct cie_entry *cie_root;
115
116/* Stack of old CFI data, for save/restore.  */
117struct cfa_save_data
118{
119  struct cfa_save_data *next;
120  offsetT cfa_offset;
121};
122
123static struct cfa_save_data *cfa_save_stack;
124
125/* Construct a new FDE structure and add it to the end of the fde list.  */
126
127static struct fde_entry *
128alloc_fde_entry (void)
129{
130  struct fde_entry *fde = xcalloc (1, sizeof (struct fde_entry));
131
132  cur_fde_data = fde;
133  *last_fde_data = fde;
134  last_fde_data = &fde->next;
135
136  fde->last = &fde->data;
137  fde->return_column = DWARF2_DEFAULT_RETURN_COLUMN;
138
139  return fde;
140}
141
142/* The following functions are available for a backend to construct its
143   own unwind information, usually from legacy unwind directives.  */
144
145/* Construct a new INSN structure and add it to the end of the insn list
146   for the currently active FDE.  */
147
148static struct cfi_insn_data *
149alloc_cfi_insn_data (void)
150{
151  struct cfi_insn_data *insn = xcalloc (1, sizeof (struct cfi_insn_data));
152
153  *cur_fde_data->last = insn;
154  cur_fde_data->last = &insn->next;
155
156  return insn;
157}
158
159/* Construct a new FDE structure that begins at LABEL.  */
160
161void
162cfi_new_fde (symbolS *label)
163{
164  struct fde_entry *fde = alloc_fde_entry ();
165  fde->start_address = label;
166  last_address = label;
167}
168
169/* End the currently open FDE.  */
170
171void
172cfi_end_fde (symbolS *label)
173{
174  cur_fde_data->end_address = label;
175  cur_fde_data = NULL;
176}
177
178/* Set the return column for the current FDE.  */
179
180void
181cfi_set_return_column (unsigned regno)
182{
183  cur_fde_data->return_column = regno;
184}
185
186/* Universal functions to store new instructions.  */
187
188static void
189cfi_add_CFA_insn(int insn)
190{
191  struct cfi_insn_data *insn_ptr = alloc_cfi_insn_data ();
192
193  insn_ptr->insn = insn;
194}
195
196static void
197cfi_add_CFA_insn_reg (int insn, unsigned regno)
198{
199  struct cfi_insn_data *insn_ptr = alloc_cfi_insn_data ();
200
201  insn_ptr->insn = insn;
202  insn_ptr->u.r = regno;
203}
204
205static void
206cfi_add_CFA_insn_offset (int insn, offsetT offset)
207{
208  struct cfi_insn_data *insn_ptr = alloc_cfi_insn_data ();
209
210  insn_ptr->insn = insn;
211  insn_ptr->u.i = offset;
212}
213
214static void
215cfi_add_CFA_insn_reg_reg (int insn, unsigned reg1, unsigned reg2)
216{
217  struct cfi_insn_data *insn_ptr = alloc_cfi_insn_data ();
218
219  insn_ptr->insn = insn;
220  insn_ptr->u.rr.reg1 = reg1;
221  insn_ptr->u.rr.reg2 = reg2;
222}
223
224static void
225cfi_add_CFA_insn_reg_offset (int insn, unsigned regno, offsetT offset)
226{
227  struct cfi_insn_data *insn_ptr = alloc_cfi_insn_data ();
228
229  insn_ptr->insn = insn;
230  insn_ptr->u.ri.reg = regno;
231  insn_ptr->u.ri.offset = offset;
232}
233
234/* Add a CFI insn to advance the PC from the last address to LABEL.  */
235
236void
237cfi_add_advance_loc (symbolS *label)
238{
239  struct cfi_insn_data *insn = alloc_cfi_insn_data ();
240
241  insn->insn = DW_CFA_advance_loc;
242  insn->u.ll.lab1 = last_address;
243  insn->u.ll.lab2 = label;
244
245  last_address = label;
246}
247
248/* Add a DW_CFA_offset record to the CFI data.  */
249
250void
251cfi_add_CFA_offset (unsigned regno, offsetT offset)
252{
253  unsigned int abs_data_align;
254
255  cfi_add_CFA_insn_reg_offset (DW_CFA_offset, regno, offset);
256
257  abs_data_align = (DWARF2_CIE_DATA_ALIGNMENT < 0
258		    ? -DWARF2_CIE_DATA_ALIGNMENT : DWARF2_CIE_DATA_ALIGNMENT);
259  if (offset % abs_data_align)
260    as_bad (_("register save offset not a multiple of %u"), abs_data_align);
261}
262
263/* Add a DW_CFA_def_cfa record to the CFI data.  */
264
265void
266cfi_add_CFA_def_cfa (unsigned regno, offsetT offset)
267{
268  cfi_add_CFA_insn_reg_offset (DW_CFA_def_cfa, regno, offset);
269  cur_cfa_offset = offset;
270}
271
272/* Add a DW_CFA_register record to the CFI data.  */
273
274void
275cfi_add_CFA_register (unsigned reg1, unsigned reg2)
276{
277  cfi_add_CFA_insn_reg_reg (DW_CFA_register, reg1, reg2);
278}
279
280/* Add a DW_CFA_def_cfa_register record to the CFI data.  */
281
282void
283cfi_add_CFA_def_cfa_register (unsigned regno)
284{
285  cfi_add_CFA_insn_reg (DW_CFA_def_cfa_register, regno);
286}
287
288/* Add a DW_CFA_def_cfa_offset record to the CFI data.  */
289
290void
291cfi_add_CFA_def_cfa_offset (offsetT offset)
292{
293  cfi_add_CFA_insn_offset (DW_CFA_def_cfa_offset, offset);
294  cur_cfa_offset = offset;
295}
296
297void
298cfi_add_CFA_restore (unsigned regno)
299{
300  cfi_add_CFA_insn_reg (DW_CFA_restore, regno);
301}
302
303void
304cfi_add_CFA_undefined (unsigned regno)
305{
306  cfi_add_CFA_insn_reg (DW_CFA_undefined, regno);
307}
308
309void
310cfi_add_CFA_same_value (unsigned regno)
311{
312  cfi_add_CFA_insn_reg (DW_CFA_same_value, regno);
313}
314
315void
316cfi_add_CFA_remember_state (void)
317{
318  struct cfa_save_data *p;
319
320  cfi_add_CFA_insn (DW_CFA_remember_state);
321
322  p = xmalloc (sizeof (*p));
323  p->cfa_offset = cur_cfa_offset;
324  p->next = cfa_save_stack;
325  cfa_save_stack = p;
326}
327
328void
329cfi_add_CFA_restore_state (void)
330{
331  struct cfa_save_data *p;
332
333  cfi_add_CFA_insn (DW_CFA_restore_state);
334
335  p = cfa_save_stack;
336  if (p)
337    {
338      cur_cfa_offset = p->cfa_offset;
339      cfa_save_stack = p->next;
340      free (p);
341    }
342  else
343    as_bad (_("CFI state restore without previous remember"));
344}
345
346
347/* Parse CFI assembler directives.  */
348
349static void dot_cfi (int);
350static void dot_cfi_escape (int);
351static void dot_cfi_startproc (int);
352static void dot_cfi_endproc (int);
353
354/* Fake CFI type; outside the byte range of any real CFI insn.  */
355#define CFI_adjust_cfa_offset	0x100
356#define CFI_return_column	0x101
357#define CFI_rel_offset		0x102
358#define CFI_escape		0x103
359#define CFI_signal_frame	0x104
360
361const pseudo_typeS cfi_pseudo_table[] =
362  {
363    { "cfi_startproc", dot_cfi_startproc, 0 },
364    { "cfi_endproc", dot_cfi_endproc, 0 },
365    { "cfi_def_cfa", dot_cfi, DW_CFA_def_cfa },
366    { "cfi_def_cfa_register", dot_cfi, DW_CFA_def_cfa_register },
367    { "cfi_def_cfa_offset", dot_cfi, DW_CFA_def_cfa_offset },
368    { "cfi_adjust_cfa_offset", dot_cfi, CFI_adjust_cfa_offset },
369    { "cfi_offset", dot_cfi, DW_CFA_offset },
370    { "cfi_rel_offset", dot_cfi, CFI_rel_offset },
371    { "cfi_register", dot_cfi, DW_CFA_register },
372    { "cfi_return_column", dot_cfi, CFI_return_column },
373    { "cfi_restore", dot_cfi, DW_CFA_restore },
374    { "cfi_undefined", dot_cfi, DW_CFA_undefined },
375    { "cfi_same_value", dot_cfi, DW_CFA_same_value },
376    { "cfi_remember_state", dot_cfi, DW_CFA_remember_state },
377    { "cfi_restore_state", dot_cfi, DW_CFA_restore_state },
378    { "cfi_window_save", dot_cfi, DW_CFA_GNU_window_save },
379    { "cfi_escape", dot_cfi_escape, 0 },
380    { "cfi_signal_frame", dot_cfi, CFI_signal_frame },
381    { NULL, NULL, 0 }
382  };
383
384static void
385cfi_parse_separator (void)
386{
387  SKIP_WHITESPACE ();
388  if (*input_line_pointer == ',')
389    input_line_pointer++;
390  else
391    as_bad (_("missing separator"));
392}
393
394static unsigned
395cfi_parse_reg (void)
396{
397  int regno;
398  expressionS exp;
399
400#ifdef tc_regname_to_dw2regnum
401  SKIP_WHITESPACE ();
402  if (is_name_beginner (*input_line_pointer)
403      || (*input_line_pointer == '%'
404	  && is_name_beginner (*++input_line_pointer)))
405    {
406      char *name, c;
407
408      name = input_line_pointer;
409      c = get_symbol_end ();
410
411      if ((regno = tc_regname_to_dw2regnum (name)) < 0)
412	{
413	  as_bad (_("bad register expression"));
414	  regno = 0;
415	}
416
417      *input_line_pointer = c;
418      return regno;
419    }
420#endif
421
422  expression_and_evaluate (&exp);
423  switch (exp.X_op)
424    {
425    case O_register:
426    case O_constant:
427      regno = exp.X_add_number;
428      break;
429
430    default:
431      as_bad (_("bad register expression"));
432      regno = 0;
433      break;
434    }
435
436  return regno;
437}
438
439static offsetT
440cfi_parse_const (void)
441{
442  return get_absolute_expression ();
443}
444
445static void
446dot_cfi (int arg)
447{
448  offsetT offset;
449  unsigned reg1, reg2;
450
451  if (!cur_fde_data)
452    {
453      as_bad (_("CFI instruction used without previous .cfi_startproc"));
454      ignore_rest_of_line ();
455      return;
456    }
457
458  /* If the last address was not at the current PC, advance to current.  */
459  if (symbol_get_frag (last_address) != frag_now
460      || S_GET_VALUE (last_address) != frag_now_fix ())
461    cfi_add_advance_loc (symbol_temp_new_now ());
462
463  switch (arg)
464    {
465    case DW_CFA_offset:
466      reg1 = cfi_parse_reg ();
467      cfi_parse_separator ();
468      offset = cfi_parse_const ();
469      cfi_add_CFA_offset (reg1, offset);
470      break;
471
472    case CFI_rel_offset:
473      reg1 = cfi_parse_reg ();
474      cfi_parse_separator ();
475      offset = cfi_parse_const ();
476      cfi_add_CFA_offset (reg1, offset - cur_cfa_offset);
477      break;
478
479    case DW_CFA_def_cfa:
480      reg1 = cfi_parse_reg ();
481      cfi_parse_separator ();
482      offset = cfi_parse_const ();
483      cfi_add_CFA_def_cfa (reg1, offset);
484      break;
485
486    case DW_CFA_register:
487      reg1 = cfi_parse_reg ();
488      cfi_parse_separator ();
489      reg2 = cfi_parse_reg ();
490      cfi_add_CFA_register (reg1, reg2);
491      break;
492
493    case DW_CFA_def_cfa_register:
494      reg1 = cfi_parse_reg ();
495      cfi_add_CFA_def_cfa_register (reg1);
496      break;
497
498    case DW_CFA_def_cfa_offset:
499      offset = cfi_parse_const ();
500      cfi_add_CFA_def_cfa_offset (offset);
501      break;
502
503    case CFI_adjust_cfa_offset:
504      offset = cfi_parse_const ();
505      cfi_add_CFA_def_cfa_offset (cur_cfa_offset + offset);
506      break;
507
508    case DW_CFA_restore:
509      for (;;)
510	{
511	  reg1 = cfi_parse_reg ();
512	  cfi_add_CFA_restore (reg1);
513	  SKIP_WHITESPACE ();
514	  if (*input_line_pointer != ',')
515	    break;
516	  ++input_line_pointer;
517	}
518      break;
519
520    case DW_CFA_undefined:
521      for (;;)
522	{
523	  reg1 = cfi_parse_reg ();
524	  cfi_add_CFA_undefined (reg1);
525	  SKIP_WHITESPACE ();
526	  if (*input_line_pointer != ',')
527	    break;
528	  ++input_line_pointer;
529	}
530      break;
531
532    case DW_CFA_same_value:
533      reg1 = cfi_parse_reg ();
534      cfi_add_CFA_same_value (reg1);
535      break;
536
537    case CFI_return_column:
538      reg1 = cfi_parse_reg ();
539      cfi_set_return_column (reg1);
540      break;
541
542    case DW_CFA_remember_state:
543      cfi_add_CFA_remember_state ();
544      break;
545
546    case DW_CFA_restore_state:
547      cfi_add_CFA_restore_state ();
548      break;
549
550    case DW_CFA_GNU_window_save:
551      cfi_add_CFA_insn (DW_CFA_GNU_window_save);
552      break;
553
554    case CFI_signal_frame:
555      cur_fde_data->signal_frame = 1;
556      break;
557
558    default:
559      abort ();
560    }
561
562  demand_empty_rest_of_line ();
563}
564
565static void
566dot_cfi_escape (int ignored ATTRIBUTE_UNUSED)
567{
568  struct cfi_escape_data *head, **tail, *e;
569  struct cfi_insn_data *insn;
570
571  if (!cur_fde_data)
572    {
573      as_bad (_("CFI instruction used without previous .cfi_startproc"));
574      ignore_rest_of_line ();
575      return;
576    }
577
578  /* If the last address was not at the current PC, advance to current.  */
579  if (symbol_get_frag (last_address) != frag_now
580      || S_GET_VALUE (last_address) != frag_now_fix ())
581    cfi_add_advance_loc (symbol_temp_new_now ());
582
583  tail = &head;
584  do
585    {
586      e = xmalloc (sizeof (*e));
587      do_parse_cons_expression (&e->exp, 1);
588      *tail = e;
589      tail = &e->next;
590    }
591  while (*input_line_pointer++ == ',');
592  *tail = NULL;
593
594  insn = alloc_cfi_insn_data ();
595  insn->insn = CFI_escape;
596  insn->u.esc = head;
597
598  --input_line_pointer;
599  demand_empty_rest_of_line ();
600}
601
602static void
603dot_cfi_startproc (int ignored ATTRIBUTE_UNUSED)
604{
605  int simple = 0;
606
607  if (cur_fde_data)
608    {
609      as_bad (_("previous CFI entry not closed (missing .cfi_endproc)"));
610      ignore_rest_of_line ();
611      return;
612    }
613
614  cfi_new_fde (symbol_temp_new_now ());
615
616  SKIP_WHITESPACE ();
617  if (is_name_beginner (*input_line_pointer))
618    {
619      char *name, c;
620
621      name = input_line_pointer;
622      c = get_symbol_end ();
623
624      if (strcmp (name, "simple") == 0)
625	{
626	  simple = 1;
627	  *input_line_pointer = c;
628	}
629      else
630	input_line_pointer = name;
631    }
632  demand_empty_rest_of_line ();
633
634  cur_cfa_offset = 0;
635  if (!simple)
636    tc_cfi_frame_initial_instructions ();
637}
638
639static void
640dot_cfi_endproc (int ignored ATTRIBUTE_UNUSED)
641{
642  if (! cur_fde_data)
643    {
644      as_bad (_(".cfi_endproc without corresponding .cfi_startproc"));
645      ignore_rest_of_line ();
646      return;
647    }
648
649  cfi_end_fde (symbol_temp_new_now ());
650
651  demand_empty_rest_of_line ();
652}
653
654
655/* Emit a single byte into the current segment.  */
656
657static inline void
658out_one (int byte)
659{
660  FRAG_APPEND_1_CHAR (byte);
661}
662
663/* Emit a two-byte word into the current segment.  */
664
665static inline void
666out_two (int data)
667{
668  md_number_to_chars (frag_more (2), data, 2);
669}
670
671/* Emit a four byte word into the current segment.  */
672
673static inline void
674out_four (int data)
675{
676  md_number_to_chars (frag_more (4), data, 4);
677}
678
679/* Emit an unsigned "little-endian base 128" number.  */
680
681static void
682out_uleb128 (addressT value)
683{
684  output_leb128 (frag_more (sizeof_leb128 (value, 0)), value, 0);
685}
686
687/* Emit an unsigned "little-endian base 128" number.  */
688
689static void
690out_sleb128 (offsetT value)
691{
692  output_leb128 (frag_more (sizeof_leb128 (value, 1)), value, 1);
693}
694
695static void
696output_cfi_insn (struct cfi_insn_data *insn)
697{
698  offsetT offset;
699  unsigned int regno;
700
701  switch (insn->insn)
702    {
703    case DW_CFA_advance_loc:
704      {
705	symbolS *from = insn->u.ll.lab1;
706	symbolS *to = insn->u.ll.lab2;
707
708	if (symbol_get_frag (to) == symbol_get_frag (from))
709	  {
710	    addressT delta = S_GET_VALUE (to) - S_GET_VALUE (from);
711	    addressT scaled = delta / DWARF2_LINE_MIN_INSN_LENGTH;
712
713	    if (scaled <= 0x3F)
714	      out_one (DW_CFA_advance_loc + scaled);
715	    else if (delta <= 0xFF)
716	      {
717	        out_one (DW_CFA_advance_loc1);
718	        out_one (delta);
719	      }
720	    else if (delta <= 0xFFFF)
721	      {
722	        out_one (DW_CFA_advance_loc2);
723	        out_two (delta);
724	      }
725	    else
726	      {
727	        out_one (DW_CFA_advance_loc4);
728	        out_four (delta);
729	      }
730	  }
731	else
732	  {
733	    expressionS exp;
734
735	    exp.X_op = O_subtract;
736	    exp.X_add_symbol = to;
737	    exp.X_op_symbol = from;
738	    exp.X_add_number = 0;
739
740	    /* The code in ehopt.c expects that one byte of the encoding
741	       is already allocated to the frag.  This comes from the way
742	       that it scans the .eh_frame section looking first for the
743	       .byte DW_CFA_advance_loc4.  */
744	    frag_more (1);
745
746	    frag_var (rs_cfa, 4, 0, DWARF2_LINE_MIN_INSN_LENGTH << 3,
747		      make_expr_symbol (&exp), frag_now_fix () - 1,
748		      (char *) frag_now);
749	  }
750      }
751      break;
752
753    case DW_CFA_def_cfa:
754      offset = insn->u.ri.offset;
755      if (offset < 0)
756	{
757	  out_one (DW_CFA_def_cfa_sf);
758	  out_uleb128 (insn->u.ri.reg);
759	  out_sleb128 (offset / DWARF2_CIE_DATA_ALIGNMENT);
760	}
761      else
762	{
763	  out_one (DW_CFA_def_cfa);
764	  out_uleb128 (insn->u.ri.reg);
765	  out_uleb128 (offset);
766	}
767      break;
768
769    case DW_CFA_def_cfa_register:
770    case DW_CFA_undefined:
771    case DW_CFA_same_value:
772      out_one (insn->insn);
773      out_uleb128 (insn->u.r);
774      break;
775
776    case DW_CFA_def_cfa_offset:
777      offset = insn->u.i;
778      if (offset < 0)
779	{
780	  out_one (DW_CFA_def_cfa_offset_sf);
781	  out_sleb128 (offset / DWARF2_CIE_DATA_ALIGNMENT);
782	}
783      else
784	{
785	  out_one (DW_CFA_def_cfa_offset);
786	  out_uleb128 (offset);
787	}
788      break;
789
790    case DW_CFA_restore:
791      regno = insn->u.r;
792      if (regno <= 0x3F)
793	{
794	  out_one (DW_CFA_restore + regno);
795	}
796      else
797	{
798	  out_one (DW_CFA_restore_extended);
799	  out_uleb128 (regno);
800	}
801      break;
802
803    case DW_CFA_offset:
804      regno = insn->u.ri.reg;
805      offset = insn->u.ri.offset / DWARF2_CIE_DATA_ALIGNMENT;
806      if (offset < 0)
807	{
808	  out_one (DW_CFA_offset_extended_sf);
809	  out_uleb128 (regno);
810	  out_sleb128 (offset);
811	}
812      else if (regno <= 0x3F)
813	{
814	  out_one (DW_CFA_offset + regno);
815	  out_uleb128 (offset);
816	}
817      else
818	{
819	  out_one (DW_CFA_offset_extended);
820	  out_uleb128 (regno);
821	  out_uleb128 (offset);
822	}
823      break;
824
825    case DW_CFA_register:
826      out_one (DW_CFA_register);
827      out_uleb128 (insn->u.rr.reg1);
828      out_uleb128 (insn->u.rr.reg2);
829      break;
830
831    case DW_CFA_remember_state:
832    case DW_CFA_restore_state:
833      out_one (insn->insn);
834      break;
835
836    case DW_CFA_GNU_window_save:
837      out_one (DW_CFA_GNU_window_save);
838      break;
839
840    case CFI_escape:
841      {
842	struct cfi_escape_data *e;
843	for (e = insn->u.esc; e ; e = e->next)
844	  emit_expr (&e->exp, 1);
845	break;
846      }
847
848    default:
849      abort ();
850    }
851}
852
853static void
854output_cie (struct cie_entry *cie)
855{
856  symbolS *after_size_address, *end_address;
857  expressionS exp;
858  struct cfi_insn_data *i;
859
860  cie->start_address = symbol_temp_new_now ();
861  after_size_address = symbol_temp_make ();
862  end_address = symbol_temp_make ();
863
864  exp.X_op = O_subtract;
865  exp.X_add_symbol = end_address;
866  exp.X_op_symbol = after_size_address;
867  exp.X_add_number = 0;
868
869  emit_expr (&exp, 4);				/* Length.  */
870  symbol_set_value_now (after_size_address);
871  out_four (0);					/* CIE id.  */
872  out_one (DW_CIE_VERSION);			/* Version.  */
873  out_one ('z');				/* Augmentation.  */
874  out_one ('R');
875  if (cie->signal_frame)
876    out_one ('S');
877  out_one (0);
878  out_uleb128 (DWARF2_LINE_MIN_INSN_LENGTH);	/* Code alignment.  */
879  out_sleb128 (DWARF2_CIE_DATA_ALIGNMENT);	/* Data alignment.  */
880  if (DW_CIE_VERSION == 1)			/* Return column.  */
881    out_one (cie->return_column);
882  else
883    out_uleb128 (cie->return_column);
884  out_uleb128 (1);				/* Augmentation size.  */
885#if defined DIFF_EXPR_OK || defined tc_cfi_emit_pcrel_expr
886  out_one (DW_EH_PE_pcrel | DW_EH_PE_sdata4);
887#else
888  out_one (DW_EH_PE_sdata4);
889#endif
890
891  if (cie->first)
892    for (i = cie->first; i != cie->last; i = i->next)
893      output_cfi_insn (i);
894
895  frag_align (2, DW_CFA_nop, 0);
896  symbol_set_value_now (end_address);
897}
898
899static void
900output_fde (struct fde_entry *fde, struct cie_entry *cie,
901	    struct cfi_insn_data *first, int align)
902{
903  symbolS *after_size_address, *end_address;
904  expressionS exp;
905
906  after_size_address = symbol_temp_make ();
907  end_address = symbol_temp_make ();
908
909  exp.X_op = O_subtract;
910  exp.X_add_symbol = end_address;
911  exp.X_op_symbol = after_size_address;
912  exp.X_add_number = 0;
913  emit_expr (&exp, 4);				/* Length.  */
914  symbol_set_value_now (after_size_address);
915
916  exp.X_add_symbol = after_size_address;
917  exp.X_op_symbol = cie->start_address;
918  emit_expr (&exp, 4);				/* CIE offset.  */
919
920#ifdef DIFF_EXPR_OK
921  exp.X_add_symbol = fde->start_address;
922  exp.X_op_symbol = symbol_temp_new_now ();
923  emit_expr (&exp, 4);				/* Code offset.  */
924#else
925  exp.X_op = O_symbol;
926  exp.X_add_symbol = fde->start_address;
927  exp.X_op_symbol = NULL;
928#ifdef tc_cfi_emit_pcrel_expr
929  tc_cfi_emit_pcrel_expr (&exp, 4);		/* Code offset.  */
930#else
931  emit_expr (&exp, 4);				/* Code offset.  */
932#endif
933  exp.X_op = O_subtract;
934#endif
935
936  exp.X_add_symbol = fde->end_address;
937  exp.X_op_symbol = fde->start_address;		/* Code length.  */
938  emit_expr (&exp, 4);
939
940  out_uleb128 (0);				/* Augmentation size.  */
941
942  for (; first; first = first->next)
943    output_cfi_insn (first);
944
945  frag_align (align, DW_CFA_nop, 0);
946  symbol_set_value_now (end_address);
947}
948
949static struct cie_entry *
950select_cie_for_fde (struct fde_entry *fde, struct cfi_insn_data **pfirst)
951{
952  struct cfi_insn_data *i, *j;
953  struct cie_entry *cie;
954
955  for (cie = cie_root; cie; cie = cie->next)
956    {
957      if (cie->return_column != fde->return_column
958	  || cie->signal_frame != fde->signal_frame)
959	continue;
960      for (i = cie->first, j = fde->data;
961	   i != cie->last && j != NULL;
962	   i = i->next, j = j->next)
963	{
964	  if (i->insn != j->insn)
965	    goto fail;
966	  switch (i->insn)
967	    {
968	    case DW_CFA_advance_loc:
969	    case DW_CFA_remember_state:
970	      /* We reached the first advance/remember in the FDE,
971		 but did not reach the end of the CIE list.  */
972	      goto fail;
973
974	    case DW_CFA_offset:
975	    case DW_CFA_def_cfa:
976	      if (i->u.ri.reg != j->u.ri.reg)
977		goto fail;
978	      if (i->u.ri.offset != j->u.ri.offset)
979		goto fail;
980	      break;
981
982	    case DW_CFA_register:
983	      if (i->u.rr.reg1 != j->u.rr.reg1)
984		goto fail;
985	      if (i->u.rr.reg2 != j->u.rr.reg2)
986		goto fail;
987	      break;
988
989	    case DW_CFA_def_cfa_register:
990	    case DW_CFA_restore:
991	    case DW_CFA_undefined:
992	    case DW_CFA_same_value:
993	      if (i->u.r != j->u.r)
994		goto fail;
995	      break;
996
997	    case DW_CFA_def_cfa_offset:
998	      if (i->u.i != j->u.i)
999		goto fail;
1000	      break;
1001
1002	    case CFI_escape:
1003	      /* Don't bother matching these for now.  */
1004	      goto fail;
1005
1006	    default:
1007	      abort ();
1008	    }
1009	}
1010
1011      /* Success if we reached the end of the CIE list, and we've either
1012	 run out of FDE entries or we've encountered an advance,
1013	 remember, or escape.  */
1014      if (i == cie->last
1015	  && (!j
1016	      || j->insn == DW_CFA_advance_loc
1017	      || j->insn == DW_CFA_remember_state
1018	      || j->insn == CFI_escape))
1019	{
1020	  *pfirst = j;
1021	  return cie;
1022	}
1023
1024    fail:;
1025    }
1026
1027  cie = xmalloc (sizeof (struct cie_entry));
1028  cie->next = cie_root;
1029  cie_root = cie;
1030  cie->return_column = fde->return_column;
1031  cie->signal_frame = fde->signal_frame;
1032  cie->first = fde->data;
1033
1034  for (i = cie->first; i ; i = i->next)
1035    if (i->insn == DW_CFA_advance_loc
1036	|| i->insn == DW_CFA_remember_state
1037	|| i->insn == CFI_escape)
1038      break;
1039
1040  cie->last = i;
1041  *pfirst = i;
1042
1043  output_cie (cie);
1044
1045  return cie;
1046}
1047
1048void
1049cfi_finish (void)
1050{
1051  segT cfi_seg;
1052  struct fde_entry *fde;
1053  int save_flag_traditional_format;
1054
1055  if (cur_fde_data)
1056    {
1057      as_bad (_("open CFI at the end of file; missing .cfi_endproc directive"));
1058      cur_fde_data->end_address = cur_fde_data->start_address;
1059    }
1060
1061  if (all_fde_data == 0)
1062    return;
1063
1064  /* Open .eh_frame section.  */
1065  cfi_seg = subseg_new (".eh_frame", 0);
1066  bfd_set_section_flags (stdoutput, cfi_seg,
1067			 SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_READONLY);
1068  subseg_set (cfi_seg, 0);
1069  record_alignment (cfi_seg, EH_FRAME_ALIGNMENT);
1070
1071  /* Make sure check_eh_frame doesn't do anything with our output.  */
1072  save_flag_traditional_format = flag_traditional_format;
1073  flag_traditional_format = 1;
1074
1075  for (fde = all_fde_data; fde ; fde = fde->next)
1076    {
1077      struct cfi_insn_data *first;
1078      struct cie_entry *cie;
1079
1080      cie = select_cie_for_fde (fde, &first);
1081      output_fde (fde, cie, first, fde->next == NULL ? EH_FRAME_ALIGNMENT : 2);
1082    }
1083
1084  flag_traditional_format = save_flag_traditional_format;
1085}
1086