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