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#include "subsegs.h"
25
26
27/* We re-use DWARF2_LINE_MIN_INSN_LENGTH for the code alignment field
28   of the CIE.  Default to 1 if not otherwise specified.  */
29#ifndef  DWARF2_LINE_MIN_INSN_LENGTH
30# define DWARF2_LINE_MIN_INSN_LENGTH 1
31#endif
32
33/* If TARGET_USE_CFIPOP is defined, it is required that the target
34   provide the following definitions.  Otherwise provide them to
35   allow compilation to continue.  */
36#ifndef TARGET_USE_CFIPOP
37# ifndef  DWARF2_DEFAULT_RETURN_COLUMN
38#  define DWARF2_DEFAULT_RETURN_COLUMN 0
39# endif
40# ifndef  DWARF2_CIE_DATA_ALIGNMENT
41#  define DWARF2_CIE_DATA_ALIGNMENT 1
42# endif
43#endif
44
45#ifndef EH_FRAME_ALIGNMENT
46# define EH_FRAME_ALIGNMENT (bfd_get_arch_size (stdoutput) == 64 ? 3 : 2)
47#endif
48
49#ifndef tc_cfi_frame_initial_instructions
50# define tc_cfi_frame_initial_instructions() ((void)0)
51#endif
52
53
54struct cfi_insn_data
55{
56  struct cfi_insn_data *next;
57  int insn;
58  union {
59    struct {
60      unsigned reg;
61      offsetT offset;
62    } ri;
63
64    struct {
65      unsigned reg1;
66      unsigned reg2;
67    } rr;
68
69    unsigned r;
70    offsetT i;
71
72    struct {
73      symbolS *lab1;
74      symbolS *lab2;
75    } ll;
76
77    struct cfi_escape_data {
78      struct cfi_escape_data *next;
79      expressionS exp;
80    } *esc;
81  } u;
82};
83
84struct fde_entry
85{
86  struct fde_entry *next;
87  symbolS *start_address;
88  symbolS *end_address;
89  struct cfi_insn_data *data;
90  struct cfi_insn_data **last;
91  unsigned char per_encoding;
92  unsigned char lsda_encoding;
93  expressionS personality;
94  expressionS lsda;
95  unsigned int return_column;
96  unsigned int signal_frame;
97};
98
99struct cie_entry
100{
101  struct cie_entry *next;
102  symbolS *start_address;
103  unsigned int return_column;
104  unsigned int signal_frame;
105  unsigned char per_encoding;
106  unsigned char lsda_encoding;
107  expressionS personality;
108  struct cfi_insn_data *first, *last;
109};
110
111
112/* List of FDE entries.  */
113static struct fde_entry *all_fde_data;
114static struct fde_entry **last_fde_data = &all_fde_data;
115
116/* List of CIEs so that they could be reused.  */
117static struct cie_entry *cie_root;
118
119/* Stack of old CFI data, for save/restore.  */
120struct cfa_save_data
121{
122  struct cfa_save_data *next;
123  offsetT cfa_offset;
124};
125
126/* Current open FDE entry.  */
127struct frch_cfi_data
128{
129  struct fde_entry *cur_fde_data;
130  symbolS *last_address;
131  offsetT cur_cfa_offset;
132  struct cfa_save_data *cfa_save_stack;
133};
134
135/* Construct a new FDE structure and add it to the end of the fde list.  */
136
137static struct fde_entry *
138alloc_fde_entry (void)
139{
140  struct fde_entry *fde = xcalloc (1, sizeof (struct fde_entry));
141
142  frchain_now->frch_cfi_data = xcalloc (1, sizeof (struct frch_cfi_data));
143  frchain_now->frch_cfi_data->cur_fde_data = fde;
144  *last_fde_data = fde;
145  last_fde_data = &fde->next;
146
147  fde->last = &fde->data;
148  fde->return_column = DWARF2_DEFAULT_RETURN_COLUMN;
149  fde->per_encoding = DW_EH_PE_omit;
150  fde->lsda_encoding = DW_EH_PE_omit;
151
152  return fde;
153}
154
155/* The following functions are available for a backend to construct its
156   own unwind information, usually from legacy unwind directives.  */
157
158/* Construct a new INSN structure and add it to the end of the insn list
159   for the currently active FDE.  */
160
161static struct cfi_insn_data *
162alloc_cfi_insn_data (void)
163{
164  struct cfi_insn_data *insn = xcalloc (1, sizeof (struct cfi_insn_data));
165  struct fde_entry *cur_fde_data = frchain_now->frch_cfi_data->cur_fde_data;
166
167  *cur_fde_data->last = insn;
168  cur_fde_data->last = &insn->next;
169
170  return insn;
171}
172
173/* Construct a new FDE structure that begins at LABEL.  */
174
175void
176cfi_new_fde (symbolS *label)
177{
178  struct fde_entry *fde = alloc_fde_entry ();
179  fde->start_address = label;
180  frchain_now->frch_cfi_data->last_address = label;
181}
182
183/* End the currently open FDE.  */
184
185void
186cfi_end_fde (symbolS *label)
187{
188  frchain_now->frch_cfi_data->cur_fde_data->end_address = label;
189  free (frchain_now->frch_cfi_data);
190  frchain_now->frch_cfi_data = NULL;
191}
192
193/* Set the return column for the current FDE.  */
194
195void
196cfi_set_return_column (unsigned regno)
197{
198  frchain_now->frch_cfi_data->cur_fde_data->return_column = regno;
199}
200
201/* Universal functions to store new instructions.  */
202
203static void
204cfi_add_CFA_insn(int insn)
205{
206  struct cfi_insn_data *insn_ptr = alloc_cfi_insn_data ();
207
208  insn_ptr->insn = insn;
209}
210
211static void
212cfi_add_CFA_insn_reg (int insn, unsigned regno)
213{
214  struct cfi_insn_data *insn_ptr = alloc_cfi_insn_data ();
215
216  insn_ptr->insn = insn;
217  insn_ptr->u.r = regno;
218}
219
220static void
221cfi_add_CFA_insn_offset (int insn, offsetT offset)
222{
223  struct cfi_insn_data *insn_ptr = alloc_cfi_insn_data ();
224
225  insn_ptr->insn = insn;
226  insn_ptr->u.i = offset;
227}
228
229static void
230cfi_add_CFA_insn_reg_reg (int insn, unsigned reg1, unsigned reg2)
231{
232  struct cfi_insn_data *insn_ptr = alloc_cfi_insn_data ();
233
234  insn_ptr->insn = insn;
235  insn_ptr->u.rr.reg1 = reg1;
236  insn_ptr->u.rr.reg2 = reg2;
237}
238
239static void
240cfi_add_CFA_insn_reg_offset (int insn, unsigned regno, offsetT offset)
241{
242  struct cfi_insn_data *insn_ptr = alloc_cfi_insn_data ();
243
244  insn_ptr->insn = insn;
245  insn_ptr->u.ri.reg = regno;
246  insn_ptr->u.ri.offset = offset;
247}
248
249/* Add a CFI insn to advance the PC from the last address to LABEL.  */
250
251void
252cfi_add_advance_loc (symbolS *label)
253{
254  struct cfi_insn_data *insn = alloc_cfi_insn_data ();
255
256  insn->insn = DW_CFA_advance_loc;
257  insn->u.ll.lab1 = frchain_now->frch_cfi_data->last_address;
258  insn->u.ll.lab2 = label;
259
260  frchain_now->frch_cfi_data->last_address = label;
261}
262
263/* Add a DW_CFA_offset record to the CFI data.  */
264
265void
266cfi_add_CFA_offset (unsigned regno, offsetT offset)
267{
268  unsigned int abs_data_align;
269
270  assert (DWARF2_CIE_DATA_ALIGNMENT != 0);
271  cfi_add_CFA_insn_reg_offset (DW_CFA_offset, regno, offset);
272
273  abs_data_align = (DWARF2_CIE_DATA_ALIGNMENT < 0
274		    ? -DWARF2_CIE_DATA_ALIGNMENT : DWARF2_CIE_DATA_ALIGNMENT);
275  if (offset % abs_data_align)
276    as_bad (_("register save offset not a multiple of %u"), abs_data_align);
277}
278
279/* Add a DW_CFA_def_cfa record to the CFI data.  */
280
281void
282cfi_add_CFA_def_cfa (unsigned regno, offsetT offset)
283{
284  cfi_add_CFA_insn_reg_offset (DW_CFA_def_cfa, regno, offset);
285  frchain_now->frch_cfi_data->cur_cfa_offset = offset;
286}
287
288/* Add a DW_CFA_register record to the CFI data.  */
289
290void
291cfi_add_CFA_register (unsigned reg1, unsigned reg2)
292{
293  cfi_add_CFA_insn_reg_reg (DW_CFA_register, reg1, reg2);
294}
295
296/* Add a DW_CFA_def_cfa_register record to the CFI data.  */
297
298void
299cfi_add_CFA_def_cfa_register (unsigned regno)
300{
301  cfi_add_CFA_insn_reg (DW_CFA_def_cfa_register, regno);
302}
303
304/* Add a DW_CFA_def_cfa_offset record to the CFI data.  */
305
306void
307cfi_add_CFA_def_cfa_offset (offsetT offset)
308{
309  cfi_add_CFA_insn_offset (DW_CFA_def_cfa_offset, offset);
310  frchain_now->frch_cfi_data->cur_cfa_offset = offset;
311}
312
313void
314cfi_add_CFA_restore (unsigned regno)
315{
316  cfi_add_CFA_insn_reg (DW_CFA_restore, regno);
317}
318
319void
320cfi_add_CFA_undefined (unsigned regno)
321{
322  cfi_add_CFA_insn_reg (DW_CFA_undefined, regno);
323}
324
325void
326cfi_add_CFA_same_value (unsigned regno)
327{
328  cfi_add_CFA_insn_reg (DW_CFA_same_value, regno);
329}
330
331void
332cfi_add_CFA_remember_state (void)
333{
334  struct cfa_save_data *p;
335
336  cfi_add_CFA_insn (DW_CFA_remember_state);
337
338  p = xmalloc (sizeof (*p));
339  p->cfa_offset = frchain_now->frch_cfi_data->cur_cfa_offset;
340  p->next = frchain_now->frch_cfi_data->cfa_save_stack;
341  frchain_now->frch_cfi_data->cfa_save_stack = p;
342}
343
344void
345cfi_add_CFA_restore_state (void)
346{
347  struct cfa_save_data *p;
348
349  cfi_add_CFA_insn (DW_CFA_restore_state);
350
351  p = frchain_now->frch_cfi_data->cfa_save_stack;
352  if (p)
353    {
354      frchain_now->frch_cfi_data->cur_cfa_offset = p->cfa_offset;
355      frchain_now->frch_cfi_data->cfa_save_stack = p->next;
356      free (p);
357    }
358  else
359    as_bad (_("CFI state restore without previous remember"));
360}
361
362
363/* Parse CFI assembler directives.  */
364
365static void dot_cfi (int);
366static void dot_cfi_escape (int);
367static void dot_cfi_startproc (int);
368static void dot_cfi_endproc (int);
369static void dot_cfi_personality (int);
370static void dot_cfi_lsda (int);
371
372/* Fake CFI type; outside the byte range of any real CFI insn.  */
373#define CFI_adjust_cfa_offset	0x100
374#define CFI_return_column	0x101
375#define CFI_rel_offset		0x102
376#define CFI_escape		0x103
377#define CFI_signal_frame	0x104
378
379const pseudo_typeS cfi_pseudo_table[] =
380  {
381    { "cfi_startproc", dot_cfi_startproc, 0 },
382    { "cfi_endproc", dot_cfi_endproc, 0 },
383    { "cfi_def_cfa", dot_cfi, DW_CFA_def_cfa },
384    { "cfi_def_cfa_register", dot_cfi, DW_CFA_def_cfa_register },
385    { "cfi_def_cfa_offset", dot_cfi, DW_CFA_def_cfa_offset },
386    { "cfi_adjust_cfa_offset", dot_cfi, CFI_adjust_cfa_offset },
387    { "cfi_offset", dot_cfi, DW_CFA_offset },
388    { "cfi_rel_offset", dot_cfi, CFI_rel_offset },
389    { "cfi_register", dot_cfi, DW_CFA_register },
390    { "cfi_return_column", dot_cfi, CFI_return_column },
391    { "cfi_restore", dot_cfi, DW_CFA_restore },
392    { "cfi_undefined", dot_cfi, DW_CFA_undefined },
393    { "cfi_same_value", dot_cfi, DW_CFA_same_value },
394    { "cfi_remember_state", dot_cfi, DW_CFA_remember_state },
395    { "cfi_restore_state", dot_cfi, DW_CFA_restore_state },
396    { "cfi_window_save", dot_cfi, DW_CFA_GNU_window_save },
397    { "cfi_escape", dot_cfi_escape, 0 },
398    { "cfi_signal_frame", dot_cfi, CFI_signal_frame },
399    { "cfi_personality", dot_cfi_personality, 0 },
400    { "cfi_lsda", dot_cfi_lsda, 0 },
401    { NULL, NULL, 0 }
402  };
403
404static void
405cfi_parse_separator (void)
406{
407  SKIP_WHITESPACE ();
408  if (*input_line_pointer == ',')
409    input_line_pointer++;
410  else
411    as_bad (_("missing separator"));
412}
413
414static unsigned
415cfi_parse_reg (void)
416{
417  int regno;
418  expressionS exp;
419
420#ifdef tc_regname_to_dw2regnum
421  SKIP_WHITESPACE ();
422  if (is_name_beginner (*input_line_pointer)
423      || (*input_line_pointer == '%'
424	  && is_name_beginner (*++input_line_pointer)))
425    {
426      char *name, c;
427
428      name = input_line_pointer;
429      c = get_symbol_end ();
430
431      if ((regno = tc_regname_to_dw2regnum (name)) < 0)
432	{
433	  as_bad (_("bad register expression"));
434	  regno = 0;
435	}
436
437      *input_line_pointer = c;
438      return regno;
439    }
440#endif
441
442  expression_and_evaluate (&exp);
443  switch (exp.X_op)
444    {
445    case O_register:
446    case O_constant:
447      regno = exp.X_add_number;
448      break;
449
450    default:
451      as_bad (_("bad register expression"));
452      regno = 0;
453      break;
454    }
455
456  return regno;
457}
458
459static offsetT
460cfi_parse_const (void)
461{
462  return get_absolute_expression ();
463}
464
465static void
466dot_cfi (int arg)
467{
468  offsetT offset;
469  unsigned reg1, reg2;
470
471  if (frchain_now->frch_cfi_data == NULL)
472    {
473      as_bad (_("CFI instruction used without previous .cfi_startproc"));
474      ignore_rest_of_line ();
475      return;
476    }
477
478  /* If the last address was not at the current PC, advance to current.  */
479  if (symbol_get_frag (frchain_now->frch_cfi_data->last_address) != frag_now
480      || S_GET_VALUE (frchain_now->frch_cfi_data->last_address)
481	 != frag_now_fix ())
482    cfi_add_advance_loc (symbol_temp_new_now ());
483
484  switch (arg)
485    {
486    case DW_CFA_offset:
487      reg1 = cfi_parse_reg ();
488      cfi_parse_separator ();
489      offset = cfi_parse_const ();
490      cfi_add_CFA_offset (reg1, offset);
491      break;
492
493    case CFI_rel_offset:
494      reg1 = cfi_parse_reg ();
495      cfi_parse_separator ();
496      offset = cfi_parse_const ();
497      cfi_add_CFA_offset (reg1,
498			  offset - frchain_now->frch_cfi_data->cur_cfa_offset);
499      break;
500
501    case DW_CFA_def_cfa:
502      reg1 = cfi_parse_reg ();
503      cfi_parse_separator ();
504      offset = cfi_parse_const ();
505      cfi_add_CFA_def_cfa (reg1, offset);
506      break;
507
508    case DW_CFA_register:
509      reg1 = cfi_parse_reg ();
510      cfi_parse_separator ();
511      reg2 = cfi_parse_reg ();
512      cfi_add_CFA_register (reg1, reg2);
513      break;
514
515    case DW_CFA_def_cfa_register:
516      reg1 = cfi_parse_reg ();
517      cfi_add_CFA_def_cfa_register (reg1);
518      break;
519
520    case DW_CFA_def_cfa_offset:
521      offset = cfi_parse_const ();
522      cfi_add_CFA_def_cfa_offset (offset);
523      break;
524
525    case CFI_adjust_cfa_offset:
526      offset = cfi_parse_const ();
527      cfi_add_CFA_def_cfa_offset (frchain_now->frch_cfi_data->cur_cfa_offset
528				  + offset);
529      break;
530
531    case DW_CFA_restore:
532      for (;;)
533	{
534	  reg1 = cfi_parse_reg ();
535	  cfi_add_CFA_restore (reg1);
536	  SKIP_WHITESPACE ();
537	  if (*input_line_pointer != ',')
538	    break;
539	  ++input_line_pointer;
540	}
541      break;
542
543    case DW_CFA_undefined:
544      for (;;)
545	{
546	  reg1 = cfi_parse_reg ();
547	  cfi_add_CFA_undefined (reg1);
548	  SKIP_WHITESPACE ();
549	  if (*input_line_pointer != ',')
550	    break;
551	  ++input_line_pointer;
552	}
553      break;
554
555    case DW_CFA_same_value:
556      reg1 = cfi_parse_reg ();
557      cfi_add_CFA_same_value (reg1);
558      break;
559
560    case CFI_return_column:
561      reg1 = cfi_parse_reg ();
562      cfi_set_return_column (reg1);
563      break;
564
565    case DW_CFA_remember_state:
566      cfi_add_CFA_remember_state ();
567      break;
568
569    case DW_CFA_restore_state:
570      cfi_add_CFA_restore_state ();
571      break;
572
573    case DW_CFA_GNU_window_save:
574      cfi_add_CFA_insn (DW_CFA_GNU_window_save);
575      break;
576
577    case CFI_signal_frame:
578      frchain_now->frch_cfi_data->cur_fde_data->signal_frame = 1;
579      break;
580
581    default:
582      abort ();
583    }
584
585  demand_empty_rest_of_line ();
586}
587
588static void
589dot_cfi_escape (int ignored ATTRIBUTE_UNUSED)
590{
591  struct cfi_escape_data *head, **tail, *e;
592  struct cfi_insn_data *insn;
593
594  if (frchain_now->frch_cfi_data == NULL)
595    {
596      as_bad (_("CFI instruction used without previous .cfi_startproc"));
597      ignore_rest_of_line ();
598      return;
599    }
600
601  /* If the last address was not at the current PC, advance to current.  */
602  if (symbol_get_frag (frchain_now->frch_cfi_data->last_address) != frag_now
603      || S_GET_VALUE (frchain_now->frch_cfi_data->last_address)
604	 != frag_now_fix ())
605    cfi_add_advance_loc (symbol_temp_new_now ());
606
607  tail = &head;
608  do
609    {
610      e = xmalloc (sizeof (*e));
611      do_parse_cons_expression (&e->exp, 1);
612      *tail = e;
613      tail = &e->next;
614    }
615  while (*input_line_pointer++ == ',');
616  *tail = NULL;
617
618  insn = alloc_cfi_insn_data ();
619  insn->insn = CFI_escape;
620  insn->u.esc = head;
621
622  --input_line_pointer;
623  demand_empty_rest_of_line ();
624}
625
626static void
627dot_cfi_personality (int ignored ATTRIBUTE_UNUSED)
628{
629  struct fde_entry *fde;
630  offsetT encoding;
631
632  if (frchain_now->frch_cfi_data == NULL)
633    {
634      as_bad (_("CFI instruction used without previous .cfi_startproc"));
635      ignore_rest_of_line ();
636      return;
637    }
638
639  fde = frchain_now->frch_cfi_data->cur_fde_data;
640  encoding = get_absolute_expression ();
641  if (encoding == DW_EH_PE_omit)
642    {
643      demand_empty_rest_of_line ();
644      fde->per_encoding = encoding;
645      return;
646    }
647
648  if ((encoding & 0xff) != encoding
649      || ((encoding & 0x70) != 0
650#if defined DIFF_EXPR_OK || defined tc_cfi_emit_pcrel_expr
651	  && (encoding & 0x70) != DW_EH_PE_pcrel
652#endif
653	  )
654	 /* leb128 can be handled, but does something actually need it?  */
655      || (encoding & 7) == DW_EH_PE_uleb128
656      || (encoding & 7) > DW_EH_PE_udata8)
657    {
658      as_bad (_("invalid or unsupported encoding in .cfi_personality"));
659      ignore_rest_of_line ();
660      return;
661    }
662
663  if (*input_line_pointer++ != ',')
664    {
665      as_bad (_(".cfi_personality requires encoding and symbol arguments"));
666      ignore_rest_of_line ();
667      return;
668    }
669
670  expression_and_evaluate (&fde->personality);
671  switch (fde->personality.X_op)
672    {
673    case O_symbol:
674      break;
675    case O_constant:
676      if ((encoding & 0x70) == DW_EH_PE_pcrel)
677	encoding = DW_EH_PE_omit;
678      break;
679    default:
680      encoding = DW_EH_PE_omit;
681      break;
682    }
683
684  fde->per_encoding = encoding;
685
686  if (encoding == DW_EH_PE_omit)
687    {
688      as_bad (_("wrong second argument to .cfi_personality"));
689      ignore_rest_of_line ();
690      return;
691    }
692
693  demand_empty_rest_of_line ();
694}
695
696static void
697dot_cfi_lsda (int ignored ATTRIBUTE_UNUSED)
698{
699  struct fde_entry *fde;
700  offsetT encoding;
701
702  if (frchain_now->frch_cfi_data == NULL)
703    {
704      as_bad (_("CFI instruction used without previous .cfi_startproc"));
705      ignore_rest_of_line ();
706      return;
707    }
708
709  fde = frchain_now->frch_cfi_data->cur_fde_data;
710  encoding = get_absolute_expression ();
711  if (encoding == DW_EH_PE_omit)
712    {
713      demand_empty_rest_of_line ();
714      fde->lsda_encoding = encoding;
715      return;
716    }
717
718  if ((encoding & 0xff) != encoding
719      || ((encoding & 0x70) != 0
720#if defined DIFF_EXPR_OK || defined tc_cfi_emit_pcrel_expr
721	  && (encoding & 0x70) != DW_EH_PE_pcrel
722#endif
723	  )
724	 /* leb128 can be handled, but does something actually need it?  */
725      || (encoding & 7) == DW_EH_PE_uleb128
726      || (encoding & 7) > DW_EH_PE_udata8)
727    {
728      as_bad (_("invalid or unsupported encoding in .cfi_lsda"));
729      ignore_rest_of_line ();
730      return;
731    }
732
733  if (*input_line_pointer++ != ',')
734    {
735      as_bad (_(".cfi_lsda requires encoding and symbol arguments"));
736      ignore_rest_of_line ();
737      return;
738    }
739
740  fde->lsda_encoding = encoding;
741
742  expression_and_evaluate (&fde->lsda);
743  switch (fde->lsda.X_op)
744    {
745    case O_symbol:
746      break;
747    case O_constant:
748      if ((encoding & 0x70) == DW_EH_PE_pcrel)
749	encoding = DW_EH_PE_omit;
750      break;
751    default:
752      encoding = DW_EH_PE_omit;
753      break;
754    }
755
756  fde->lsda_encoding = encoding;
757
758  if (encoding == DW_EH_PE_omit)
759    {
760      as_bad (_("wrong second argument to .cfi_lsda"));
761      ignore_rest_of_line ();
762      return;
763    }
764
765  demand_empty_rest_of_line ();
766}
767
768static void
769dot_cfi_startproc (int ignored ATTRIBUTE_UNUSED)
770{
771  int simple = 0;
772
773  if (frchain_now->frch_cfi_data != NULL)
774    {
775      as_bad (_("previous CFI entry not closed (missing .cfi_endproc)"));
776      ignore_rest_of_line ();
777      return;
778    }
779
780  cfi_new_fde (symbol_temp_new_now ());
781
782  SKIP_WHITESPACE ();
783  if (is_name_beginner (*input_line_pointer))
784    {
785      char *name, c;
786
787      name = input_line_pointer;
788      c = get_symbol_end ();
789
790      if (strcmp (name, "simple") == 0)
791	{
792	  simple = 1;
793	  *input_line_pointer = c;
794	}
795      else
796	input_line_pointer = name;
797    }
798  demand_empty_rest_of_line ();
799
800  frchain_now->frch_cfi_data->cur_cfa_offset = 0;
801  if (!simple)
802    tc_cfi_frame_initial_instructions ();
803}
804
805static void
806dot_cfi_endproc (int ignored ATTRIBUTE_UNUSED)
807{
808  if (frchain_now->frch_cfi_data == NULL)
809    {
810      as_bad (_(".cfi_endproc without corresponding .cfi_startproc"));
811      ignore_rest_of_line ();
812      return;
813    }
814
815  cfi_end_fde (symbol_temp_new_now ());
816
817  demand_empty_rest_of_line ();
818}
819
820
821/* Emit a single byte into the current segment.  */
822
823static inline void
824out_one (int byte)
825{
826  FRAG_APPEND_1_CHAR (byte);
827}
828
829/* Emit a two-byte word into the current segment.  */
830
831static inline void
832out_two (int data)
833{
834  md_number_to_chars (frag_more (2), data, 2);
835}
836
837/* Emit a four byte word into the current segment.  */
838
839static inline void
840out_four (int data)
841{
842  md_number_to_chars (frag_more (4), data, 4);
843}
844
845/* Emit an unsigned "little-endian base 128" number.  */
846
847static void
848out_uleb128 (addressT value)
849{
850  output_leb128 (frag_more (sizeof_leb128 (value, 0)), value, 0);
851}
852
853/* Emit an unsigned "little-endian base 128" number.  */
854
855static void
856out_sleb128 (offsetT value)
857{
858  output_leb128 (frag_more (sizeof_leb128 (value, 1)), value, 1);
859}
860
861static void
862output_cfi_insn (struct cfi_insn_data *insn)
863{
864  offsetT offset;
865  unsigned int regno;
866
867  switch (insn->insn)
868    {
869    case DW_CFA_advance_loc:
870      {
871	symbolS *from = insn->u.ll.lab1;
872	symbolS *to = insn->u.ll.lab2;
873
874	if (symbol_get_frag (to) == symbol_get_frag (from))
875	  {
876	    addressT delta = S_GET_VALUE (to) - S_GET_VALUE (from);
877	    addressT scaled = delta / DWARF2_LINE_MIN_INSN_LENGTH;
878
879	    if (scaled <= 0x3F)
880	      out_one (DW_CFA_advance_loc + scaled);
881	    else if (delta <= 0xFF)
882	      {
883		out_one (DW_CFA_advance_loc1);
884		out_one (delta);
885	      }
886	    else if (delta <= 0xFFFF)
887	      {
888		out_one (DW_CFA_advance_loc2);
889		out_two (delta);
890	      }
891	    else
892	      {
893		out_one (DW_CFA_advance_loc4);
894		out_four (delta);
895	      }
896	  }
897	else
898	  {
899	    expressionS exp;
900
901	    exp.X_op = O_subtract;
902	    exp.X_add_symbol = to;
903	    exp.X_op_symbol = from;
904	    exp.X_add_number = 0;
905
906	    /* The code in ehopt.c expects that one byte of the encoding
907	       is already allocated to the frag.  This comes from the way
908	       that it scans the .eh_frame section looking first for the
909	       .byte DW_CFA_advance_loc4.  */
910	    frag_more (1);
911
912	    frag_var (rs_cfa, 4, 0, DWARF2_LINE_MIN_INSN_LENGTH << 3,
913		      make_expr_symbol (&exp), frag_now_fix () - 1,
914		      (char *) frag_now);
915	  }
916      }
917      break;
918
919    case DW_CFA_def_cfa:
920      offset = insn->u.ri.offset;
921      if (offset < 0)
922	{
923	  out_one (DW_CFA_def_cfa_sf);
924	  out_uleb128 (insn->u.ri.reg);
925	  out_sleb128 (offset / DWARF2_CIE_DATA_ALIGNMENT);
926	}
927      else
928	{
929	  out_one (DW_CFA_def_cfa);
930	  out_uleb128 (insn->u.ri.reg);
931	  out_uleb128 (offset);
932	}
933      break;
934
935    case DW_CFA_def_cfa_register:
936    case DW_CFA_undefined:
937    case DW_CFA_same_value:
938      out_one (insn->insn);
939      out_uleb128 (insn->u.r);
940      break;
941
942    case DW_CFA_def_cfa_offset:
943      offset = insn->u.i;
944      if (offset < 0)
945	{
946	  out_one (DW_CFA_def_cfa_offset_sf);
947	  out_sleb128 (offset / DWARF2_CIE_DATA_ALIGNMENT);
948	}
949      else
950	{
951	  out_one (DW_CFA_def_cfa_offset);
952	  out_uleb128 (offset);
953	}
954      break;
955
956    case DW_CFA_restore:
957      regno = insn->u.r;
958      if (regno <= 0x3F)
959	{
960	  out_one (DW_CFA_restore + regno);
961	}
962      else
963	{
964	  out_one (DW_CFA_restore_extended);
965	  out_uleb128 (regno);
966	}
967      break;
968
969    case DW_CFA_offset:
970      regno = insn->u.ri.reg;
971      offset = insn->u.ri.offset / DWARF2_CIE_DATA_ALIGNMENT;
972      if (offset < 0)
973	{
974	  out_one (DW_CFA_offset_extended_sf);
975	  out_uleb128 (regno);
976	  out_sleb128 (offset);
977	}
978      else if (regno <= 0x3F)
979	{
980	  out_one (DW_CFA_offset + regno);
981	  out_uleb128 (offset);
982	}
983      else
984	{
985	  out_one (DW_CFA_offset_extended);
986	  out_uleb128 (regno);
987	  out_uleb128 (offset);
988	}
989      break;
990
991    case DW_CFA_register:
992      out_one (DW_CFA_register);
993      out_uleb128 (insn->u.rr.reg1);
994      out_uleb128 (insn->u.rr.reg2);
995      break;
996
997    case DW_CFA_remember_state:
998    case DW_CFA_restore_state:
999      out_one (insn->insn);
1000      break;
1001
1002    case DW_CFA_GNU_window_save:
1003      out_one (DW_CFA_GNU_window_save);
1004      break;
1005
1006    case CFI_escape:
1007      {
1008	struct cfi_escape_data *e;
1009	for (e = insn->u.esc; e ; e = e->next)
1010	  emit_expr (&e->exp, 1);
1011	break;
1012      }
1013
1014    default:
1015      abort ();
1016    }
1017}
1018
1019static offsetT
1020encoding_size (unsigned char encoding)
1021{
1022  if (encoding == DW_EH_PE_omit)
1023    return 0;
1024  switch (encoding & 0x7)
1025    {
1026    case 0:
1027      return bfd_get_arch_size (stdoutput) == 64 ? 8 : 4;
1028    case DW_EH_PE_udata2:
1029      return 2;
1030    case DW_EH_PE_udata4:
1031      return 4;
1032    case DW_EH_PE_udata8:
1033      return 8;
1034    default:
1035      abort ();
1036    }
1037}
1038
1039static void
1040output_cie (struct cie_entry *cie)
1041{
1042  symbolS *after_size_address, *end_address;
1043  expressionS exp;
1044  struct cfi_insn_data *i;
1045  offsetT augmentation_size;
1046
1047  cie->start_address = symbol_temp_new_now ();
1048  after_size_address = symbol_temp_make ();
1049  end_address = symbol_temp_make ();
1050
1051  exp.X_op = O_subtract;
1052  exp.X_add_symbol = end_address;
1053  exp.X_op_symbol = after_size_address;
1054  exp.X_add_number = 0;
1055
1056  emit_expr (&exp, 4);				/* Length.  */
1057  symbol_set_value_now (after_size_address);
1058  out_four (0);					/* CIE id.  */
1059  out_one (DW_CIE_VERSION);			/* Version.  */
1060  out_one ('z');				/* Augmentation.  */
1061  if (cie->per_encoding != DW_EH_PE_omit)
1062    out_one ('P');
1063  if (cie->lsda_encoding != DW_EH_PE_omit)
1064    out_one ('L');
1065  out_one ('R');
1066  if (cie->signal_frame)
1067    out_one ('S');
1068  out_one (0);
1069  out_uleb128 (DWARF2_LINE_MIN_INSN_LENGTH);	/* Code alignment.  */
1070  out_sleb128 (DWARF2_CIE_DATA_ALIGNMENT);	/* Data alignment.  */
1071  if (DW_CIE_VERSION == 1)			/* Return column.  */
1072    out_one (cie->return_column);
1073  else
1074    out_uleb128 (cie->return_column);
1075  augmentation_size = 1 + (cie->lsda_encoding != DW_EH_PE_omit);
1076  if (cie->per_encoding != DW_EH_PE_omit)
1077    augmentation_size += 1 + encoding_size (cie->per_encoding);
1078  out_uleb128 (augmentation_size);		/* Augmentation size.  */
1079  if (cie->per_encoding != DW_EH_PE_omit)
1080    {
1081      offsetT size = encoding_size (cie->per_encoding);
1082      out_one (cie->per_encoding);
1083      exp = cie->personality;
1084      if ((cie->per_encoding & 0x70) == DW_EH_PE_pcrel)
1085	{
1086#ifdef DIFF_EXPR_OK
1087	  exp.X_op = O_subtract;
1088	  exp.X_op_symbol = symbol_temp_new_now ();
1089	  emit_expr (&exp, size);
1090#elif defined (tc_cfi_emit_pcrel_expr)
1091	  tc_cfi_emit_pcrel_expr (&exp, size);
1092#else
1093	  abort ();
1094#endif
1095	}
1096      else
1097	emit_expr (&exp, size);
1098    }
1099  if (cie->lsda_encoding != DW_EH_PE_omit)
1100    out_one (cie->lsda_encoding);
1101#if defined DIFF_EXPR_OK || defined tc_cfi_emit_pcrel_expr
1102  out_one (DW_EH_PE_pcrel | DW_EH_PE_sdata4);
1103#else
1104  out_one (DW_EH_PE_sdata4);
1105#endif
1106
1107  if (cie->first)
1108    for (i = cie->first; i != cie->last; i = i->next)
1109      output_cfi_insn (i);
1110
1111  frag_align (2, DW_CFA_nop, 0);
1112  symbol_set_value_now (end_address);
1113}
1114
1115static void
1116output_fde (struct fde_entry *fde, struct cie_entry *cie,
1117	    struct cfi_insn_data *first, int align)
1118{
1119  symbolS *after_size_address, *end_address;
1120  expressionS exp;
1121  offsetT augmentation_size;
1122
1123  after_size_address = symbol_temp_make ();
1124  end_address = symbol_temp_make ();
1125
1126  exp.X_op = O_subtract;
1127  exp.X_add_symbol = end_address;
1128  exp.X_op_symbol = after_size_address;
1129  exp.X_add_number = 0;
1130  emit_expr (&exp, 4);				/* Length.  */
1131  symbol_set_value_now (after_size_address);
1132
1133  exp.X_add_symbol = after_size_address;
1134  exp.X_op_symbol = cie->start_address;
1135  emit_expr (&exp, 4);				/* CIE offset.  */
1136
1137#ifdef DIFF_EXPR_OK
1138  exp.X_add_symbol = fde->start_address;
1139  exp.X_op_symbol = symbol_temp_new_now ();
1140  emit_expr (&exp, 4);				/* Code offset.  */
1141#else
1142  exp.X_op = O_symbol;
1143  exp.X_add_symbol = fde->start_address;
1144  exp.X_op_symbol = NULL;
1145#ifdef tc_cfi_emit_pcrel_expr
1146  tc_cfi_emit_pcrel_expr (&exp, 4);		/* Code offset.  */
1147#else
1148  emit_expr (&exp, 4);				/* Code offset.  */
1149#endif
1150  exp.X_op = O_subtract;
1151#endif
1152
1153  exp.X_add_symbol = fde->end_address;
1154  exp.X_op_symbol = fde->start_address;		/* Code length.  */
1155  emit_expr (&exp, 4);
1156
1157  augmentation_size = encoding_size (fde->lsda_encoding);
1158  out_uleb128 (augmentation_size);		/* Augmentation size.  */
1159
1160  if (fde->lsda_encoding != DW_EH_PE_omit)
1161    {
1162      exp = fde->lsda;
1163      if ((fde->lsda_encoding & 0x70) == DW_EH_PE_pcrel)
1164	{
1165#ifdef DIFF_EXPR_OK
1166	  exp.X_op = O_subtract;
1167	  exp.X_op_symbol = symbol_temp_new_now ();
1168	  emit_expr (&exp, augmentation_size);
1169#elif defined (tc_cfi_emit_pcrel_expr)
1170	  tc_cfi_emit_pcrel_expr (&exp, augmentation_size);
1171#else
1172	  abort ();
1173#endif
1174	}
1175      else
1176	emit_expr (&exp, augmentation_size);
1177    }
1178
1179  for (; first; first = first->next)
1180    output_cfi_insn (first);
1181
1182  frag_align (align, DW_CFA_nop, 0);
1183  symbol_set_value_now (end_address);
1184}
1185
1186static struct cie_entry *
1187select_cie_for_fde (struct fde_entry *fde, struct cfi_insn_data **pfirst)
1188{
1189  struct cfi_insn_data *i, *j;
1190  struct cie_entry *cie;
1191
1192  for (cie = cie_root; cie; cie = cie->next)
1193    {
1194      if (cie->return_column != fde->return_column
1195	  || cie->signal_frame != fde->signal_frame
1196	  || cie->per_encoding != fde->per_encoding
1197	  || cie->lsda_encoding != fde->lsda_encoding)
1198	continue;
1199      if (cie->per_encoding != DW_EH_PE_omit)
1200	{
1201	  if (cie->personality.X_op != fde->personality.X_op
1202	      || cie->personality.X_add_number
1203		 != fde->personality.X_add_number)
1204	    continue;
1205	  switch (cie->personality.X_op)
1206	    {
1207	    case O_constant:
1208	      if (cie->personality.X_unsigned != fde->personality.X_unsigned)
1209		continue;
1210	      break;
1211	    case O_symbol:
1212	      if (cie->personality.X_add_symbol
1213		  != fde->personality.X_add_symbol)
1214		continue;
1215	      break;
1216	    default:
1217	      abort ();
1218	    }
1219	}
1220      for (i = cie->first, j = fde->data;
1221	   i != cie->last && j != NULL;
1222	   i = i->next, j = j->next)
1223	{
1224	  if (i->insn != j->insn)
1225	    goto fail;
1226	  switch (i->insn)
1227	    {
1228	    case DW_CFA_advance_loc:
1229	    case DW_CFA_remember_state:
1230	      /* We reached the first advance/remember in the FDE,
1231		 but did not reach the end of the CIE list.  */
1232	      goto fail;
1233
1234	    case DW_CFA_offset:
1235	    case DW_CFA_def_cfa:
1236	      if (i->u.ri.reg != j->u.ri.reg)
1237		goto fail;
1238	      if (i->u.ri.offset != j->u.ri.offset)
1239		goto fail;
1240	      break;
1241
1242	    case DW_CFA_register:
1243	      if (i->u.rr.reg1 != j->u.rr.reg1)
1244		goto fail;
1245	      if (i->u.rr.reg2 != j->u.rr.reg2)
1246		goto fail;
1247	      break;
1248
1249	    case DW_CFA_def_cfa_register:
1250	    case DW_CFA_restore:
1251	    case DW_CFA_undefined:
1252	    case DW_CFA_same_value:
1253	      if (i->u.r != j->u.r)
1254		goto fail;
1255	      break;
1256
1257	    case DW_CFA_def_cfa_offset:
1258	      if (i->u.i != j->u.i)
1259		goto fail;
1260	      break;
1261
1262	    case CFI_escape:
1263	      /* Don't bother matching these for now.  */
1264	      goto fail;
1265
1266	    default:
1267	      abort ();
1268	    }
1269	}
1270
1271      /* Success if we reached the end of the CIE list, and we've either
1272	 run out of FDE entries or we've encountered an advance,
1273	 remember, or escape.  */
1274      if (i == cie->last
1275	  && (!j
1276	      || j->insn == DW_CFA_advance_loc
1277	      || j->insn == DW_CFA_remember_state
1278	      || j->insn == CFI_escape))
1279	{
1280	  *pfirst = j;
1281	  return cie;
1282	}
1283
1284    fail:;
1285    }
1286
1287  cie = xmalloc (sizeof (struct cie_entry));
1288  cie->next = cie_root;
1289  cie_root = cie;
1290  cie->return_column = fde->return_column;
1291  cie->signal_frame = fde->signal_frame;
1292  cie->per_encoding = fde->per_encoding;
1293  cie->lsda_encoding = fde->lsda_encoding;
1294  cie->personality = fde->personality;
1295  cie->first = fde->data;
1296
1297  for (i = cie->first; i ; i = i->next)
1298    if (i->insn == DW_CFA_advance_loc
1299	|| i->insn == DW_CFA_remember_state
1300	|| i->insn == CFI_escape)
1301      break;
1302
1303  cie->last = i;
1304  *pfirst = i;
1305
1306  output_cie (cie);
1307
1308  return cie;
1309}
1310
1311void
1312cfi_finish (void)
1313{
1314  segT cfi_seg;
1315  struct fde_entry *fde;
1316  int save_flag_traditional_format;
1317
1318  if (all_fde_data == 0)
1319    return;
1320
1321  /* Open .eh_frame section.  */
1322  cfi_seg = subseg_new (".eh_frame", 0);
1323  bfd_set_section_flags (stdoutput, cfi_seg,
1324			 SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_READONLY);
1325  subseg_set (cfi_seg, 0);
1326  record_alignment (cfi_seg, EH_FRAME_ALIGNMENT);
1327
1328  /* Make sure check_eh_frame doesn't do anything with our output.  */
1329  save_flag_traditional_format = flag_traditional_format;
1330  flag_traditional_format = 1;
1331
1332  for (fde = all_fde_data; fde ; fde = fde->next)
1333    {
1334      struct cfi_insn_data *first;
1335      struct cie_entry *cie;
1336
1337      if (fde->end_address == NULL)
1338	{
1339	  as_bad (_("open CFI at the end of file; missing .cfi_endproc directive"));
1340	  fde->end_address = fde->start_address;
1341	}
1342
1343      cie = select_cie_for_fde (fde, &first);
1344      output_fde (fde, cie, first, fde->next == NULL ? EH_FRAME_ALIGNMENT : 2);
1345    }
1346
1347  flag_traditional_format = save_flag_traditional_format;
1348}
1349