d7ebf8c0ae89cc96de09f48f627a27d4a6b0b82a
[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 #ifndef tc_parse_to_dw2regnum
404 static void
405 tc_parse_to_dw2regnum(expressionS *exp)
406 {
407 # ifdef tc_regname_to_dw2regnum
408   SKIP_WHITESPACE ();
409   if (is_name_beginner (*input_line_pointer)
410       || (*input_line_pointer == '%'
411           && is_name_beginner (*++input_line_pointer)))
412     {
413       char *name, c;
414
415       name = input_line_pointer;
416       c = get_symbol_end ();
417
418       exp->X_op = O_constant;
419       exp->X_add_number = tc_regname_to_dw2regnum (name);
420
421       *input_line_pointer = c;
422     }
423   else
424 # endif
425     expression_and_evaluate (exp);
426 }
427 #endif
428
429 static unsigned
430 cfi_parse_reg (void)
431 {
432   int regno;
433   expressionS exp;
434
435   tc_parse_to_dw2regnum (&exp);
436   switch (exp.X_op)
437     {
438     case O_register:
439     case O_constant:
440       regno = exp.X_add_number;
441       break;
442
443     default:
444       regno = -1;
445       break;
446     }
447
448   if (regno < 0)
449     {
450       as_bad (_("bad register expression"));
451       regno = 0;
452     }
453
454   return regno;
455 }
456
457 static offsetT
458 cfi_parse_const (void)
459 {
460   return get_absolute_expression ();
461 }
462
463 static void
464 dot_cfi (int arg)
465 {
466   offsetT offset;
467   unsigned reg1, reg2;
468
469   if (frchain_now->frch_cfi_data == NULL)
470     {
471       as_bad (_("CFI instruction used without previous .cfi_startproc"));
472       ignore_rest_of_line ();
473       return;
474     }
475
476   /* If the last address was not at the current PC, advance to current.  */
477   if (symbol_get_frag (frchain_now->frch_cfi_data->last_address) != frag_now
478       || S_GET_VALUE (frchain_now->frch_cfi_data->last_address)
479          != frag_now_fix ())
480     cfi_add_advance_loc (symbol_temp_new_now ());
481
482   switch (arg)
483     {
484     case DW_CFA_offset:
485       reg1 = cfi_parse_reg ();
486       cfi_parse_separator ();
487       offset = cfi_parse_const ();
488       cfi_add_CFA_offset (reg1, offset);
489       break;
490
491     case CFI_rel_offset:
492       reg1 = cfi_parse_reg ();
493       cfi_parse_separator ();
494       offset = cfi_parse_const ();
495       cfi_add_CFA_offset (reg1,
496                           offset - frchain_now->frch_cfi_data->cur_cfa_offset);
497       break;
498
499     case DW_CFA_def_cfa:
500       reg1 = cfi_parse_reg ();
501       cfi_parse_separator ();
502       offset = cfi_parse_const ();
503       cfi_add_CFA_def_cfa (reg1, offset);
504       break;
505
506     case DW_CFA_register:
507       reg1 = cfi_parse_reg ();
508       cfi_parse_separator ();
509       reg2 = cfi_parse_reg ();
510       cfi_add_CFA_register (reg1, reg2);
511       break;
512
513     case DW_CFA_def_cfa_register:
514       reg1 = cfi_parse_reg ();
515       cfi_add_CFA_def_cfa_register (reg1);
516       break;
517
518     case DW_CFA_def_cfa_offset:
519       offset = cfi_parse_const ();
520       cfi_add_CFA_def_cfa_offset (offset);
521       break;
522
523     case CFI_adjust_cfa_offset:
524       offset = cfi_parse_const ();
525       cfi_add_CFA_def_cfa_offset (frchain_now->frch_cfi_data->cur_cfa_offset
526                                   + offset);
527       break;
528
529     case DW_CFA_restore:
530       for (;;)
531         {
532           reg1 = cfi_parse_reg ();
533           cfi_add_CFA_restore (reg1);
534           SKIP_WHITESPACE ();
535           if (*input_line_pointer != ',')
536             break;
537           ++input_line_pointer;
538         }
539       break;
540
541     case DW_CFA_undefined:
542       for (;;)
543         {
544           reg1 = cfi_parse_reg ();
545           cfi_add_CFA_undefined (reg1);
546           SKIP_WHITESPACE ();
547           if (*input_line_pointer != ',')
548             break;
549           ++input_line_pointer;
550         }
551       break;
552
553     case DW_CFA_same_value:
554       reg1 = cfi_parse_reg ();
555       cfi_add_CFA_same_value (reg1);
556       break;
557
558     case CFI_return_column:
559       reg1 = cfi_parse_reg ();
560       cfi_set_return_column (reg1);
561       break;
562
563     case DW_CFA_remember_state:
564       cfi_add_CFA_remember_state ();
565       break;
566
567     case DW_CFA_restore_state:
568       cfi_add_CFA_restore_state ();
569       break;
570
571     case DW_CFA_GNU_window_save:
572       cfi_add_CFA_insn (DW_CFA_GNU_window_save);
573       break;
574
575     case CFI_signal_frame:
576       frchain_now->frch_cfi_data->cur_fde_data->signal_frame = 1;
577       break;
578
579     default:
580       abort ();
581     }
582
583   demand_empty_rest_of_line ();
584 }
585
586 static void
587 dot_cfi_escape (int ignored ATTRIBUTE_UNUSED)
588 {
589   struct cfi_escape_data *head, **tail, *e;
590   struct cfi_insn_data *insn;
591
592   if (frchain_now->frch_cfi_data == NULL)
593     {
594       as_bad (_("CFI instruction used without previous .cfi_startproc"));
595       ignore_rest_of_line ();
596       return;
597     }
598
599   /* If the last address was not at the current PC, advance to current.  */
600   if (symbol_get_frag (frchain_now->frch_cfi_data->last_address) != frag_now
601       || S_GET_VALUE (frchain_now->frch_cfi_data->last_address)
602          != frag_now_fix ())
603     cfi_add_advance_loc (symbol_temp_new_now ());
604
605   tail = &head;
606   do
607     {
608       e = xmalloc (sizeof (*e));
609       do_parse_cons_expression (&e->exp, 1);
610       *tail = e;
611       tail = &e->next;
612     }
613   while (*input_line_pointer++ == ',');
614   *tail = NULL;
615
616   insn = alloc_cfi_insn_data ();
617   insn->insn = CFI_escape;
618   insn->u.esc = head;
619
620   --input_line_pointer;
621   demand_empty_rest_of_line ();
622 }
623
624 static void
625 dot_cfi_personality (int ignored ATTRIBUTE_UNUSED)
626 {
627   struct fde_entry *fde;
628   offsetT encoding;
629
630   if (frchain_now->frch_cfi_data == NULL)
631     {
632       as_bad (_("CFI instruction used without previous .cfi_startproc"));
633       ignore_rest_of_line ();
634       return;
635     }
636
637   fde = frchain_now->frch_cfi_data->cur_fde_data;
638   encoding = get_absolute_expression ();
639   if (encoding == DW_EH_PE_omit)
640     {
641       demand_empty_rest_of_line ();
642       fde->per_encoding = encoding;
643       return;
644     }
645
646   if ((encoding & 0xff) != encoding
647       || ((encoding & 0x70) != 0
648 #if defined DIFF_EXPR_OK || defined tc_cfi_emit_pcrel_expr
649           && (encoding & 0x70) != DW_EH_PE_pcrel
650 #endif
651           )
652          /* leb128 can be handled, but does something actually need it?  */
653       || (encoding & 7) == DW_EH_PE_uleb128
654       || (encoding & 7) > DW_EH_PE_udata8)
655     {
656       as_bad (_("invalid or unsupported encoding in .cfi_personality"));
657       ignore_rest_of_line ();
658       return;
659     }
660
661   if (*input_line_pointer++ != ',')
662     {
663       as_bad (_(".cfi_personality requires encoding and symbol arguments"));
664       ignore_rest_of_line ();
665       return;
666     }
667
668   expression_and_evaluate (&fde->personality);
669   switch (fde->personality.X_op)
670     {
671     case O_symbol:
672       break;
673     case O_constant:
674       if ((encoding & 0x70) == DW_EH_PE_pcrel)
675         encoding = DW_EH_PE_omit;
676       break;
677     default:
678       encoding = DW_EH_PE_omit;
679       break;
680     }
681
682   fde->per_encoding = encoding;
683
684   if (encoding == DW_EH_PE_omit)
685     {
686       as_bad (_("wrong second argument to .cfi_personality"));
687       ignore_rest_of_line ();
688       return;
689     }
690
691   demand_empty_rest_of_line ();
692 }
693
694 static void
695 dot_cfi_lsda (int ignored ATTRIBUTE_UNUSED)
696 {
697   struct fde_entry *fde;
698   offsetT encoding;
699
700   if (frchain_now->frch_cfi_data == NULL)
701     {
702       as_bad (_("CFI instruction used without previous .cfi_startproc"));
703       ignore_rest_of_line ();
704       return;
705     }
706
707   fde = frchain_now->frch_cfi_data->cur_fde_data;
708   encoding = get_absolute_expression ();
709   if (encoding == DW_EH_PE_omit)
710     {
711       demand_empty_rest_of_line ();
712       fde->lsda_encoding = encoding;
713       return;
714     }
715
716   if ((encoding & 0xff) != encoding
717       || ((encoding & 0x70) != 0
718 #if defined DIFF_EXPR_OK || defined tc_cfi_emit_pcrel_expr
719           && (encoding & 0x70) != DW_EH_PE_pcrel
720 #endif
721           )
722          /* leb128 can be handled, but does something actually need it?  */
723       || (encoding & 7) == DW_EH_PE_uleb128
724       || (encoding & 7) > DW_EH_PE_udata8)
725     {
726       as_bad (_("invalid or unsupported encoding in .cfi_lsda"));
727       ignore_rest_of_line ();
728       return;
729     }
730
731   if (*input_line_pointer++ != ',')
732     {
733       as_bad (_(".cfi_lsda requires encoding and symbol arguments"));
734       ignore_rest_of_line ();
735       return;
736     }
737
738   fde->lsda_encoding = encoding;
739
740   expression_and_evaluate (&fde->lsda);
741   switch (fde->lsda.X_op)
742     {
743     case O_symbol:
744       break;
745     case O_constant:
746       if ((encoding & 0x70) == DW_EH_PE_pcrel)
747         encoding = DW_EH_PE_omit;
748       break;
749     default:
750       encoding = DW_EH_PE_omit;
751       break;
752     }
753
754   fde->lsda_encoding = encoding;
755
756   if (encoding == DW_EH_PE_omit)
757     {
758       as_bad (_("wrong second argument to .cfi_lsda"));
759       ignore_rest_of_line ();
760       return;
761     }
762
763   demand_empty_rest_of_line ();
764 }
765
766 static void
767 dot_cfi_startproc (int ignored ATTRIBUTE_UNUSED)
768 {
769   int simple = 0;
770
771   if (frchain_now->frch_cfi_data != NULL)
772     {
773       as_bad (_("previous CFI entry not closed (missing .cfi_endproc)"));
774       ignore_rest_of_line ();
775       return;
776     }
777
778   cfi_new_fde (symbol_temp_new_now ());
779
780   SKIP_WHITESPACE ();
781   if (is_name_beginner (*input_line_pointer))
782     {
783       char *name, c;
784
785       name = input_line_pointer;
786       c = get_symbol_end ();
787
788       if (strcmp (name, "simple") == 0)
789         {
790           simple = 1;
791           *input_line_pointer = c;
792         }
793       else
794         input_line_pointer = name;
795     }
796   demand_empty_rest_of_line ();
797
798   frchain_now->frch_cfi_data->cur_cfa_offset = 0;
799   if (!simple)
800     tc_cfi_frame_initial_instructions ();
801 }
802
803 static void
804 dot_cfi_endproc (int ignored ATTRIBUTE_UNUSED)
805 {
806   if (frchain_now->frch_cfi_data == NULL)
807     {
808       as_bad (_(".cfi_endproc without corresponding .cfi_startproc"));
809       ignore_rest_of_line ();
810       return;
811     }
812
813   cfi_end_fde (symbol_temp_new_now ());
814
815   demand_empty_rest_of_line ();
816 }
817
818 \f
819 /* Emit a single byte into the current segment.  */
820
821 static inline void
822 out_one (int byte)
823 {
824   FRAG_APPEND_1_CHAR (byte);
825 }
826
827 /* Emit a two-byte word into the current segment.  */
828
829 static inline void
830 out_two (int data)
831 {
832   md_number_to_chars (frag_more (2), data, 2);
833 }
834
835 /* Emit a four byte word into the current segment.  */
836
837 static inline void
838 out_four (int data)
839 {
840   md_number_to_chars (frag_more (4), data, 4);
841 }
842
843 /* Emit an unsigned "little-endian base 128" number.  */
844
845 static void
846 out_uleb128 (addressT value)
847 {
848   output_leb128 (frag_more (sizeof_leb128 (value, 0)), value, 0);
849 }
850
851 /* Emit an unsigned "little-endian base 128" number.  */
852
853 static void
854 out_sleb128 (offsetT value)
855 {
856   output_leb128 (frag_more (sizeof_leb128 (value, 1)), value, 1);
857 }
858
859 static void
860 output_cfi_insn (struct cfi_insn_data *insn)
861 {
862   offsetT offset;
863   unsigned int regno;
864
865   switch (insn->insn)
866     {
867     case DW_CFA_advance_loc:
868       {
869         symbolS *from = insn->u.ll.lab1;
870         symbolS *to = insn->u.ll.lab2;
871
872         if (symbol_get_frag (to) == symbol_get_frag (from))
873           {
874             addressT delta = S_GET_VALUE (to) - S_GET_VALUE (from);
875             addressT scaled = delta / DWARF2_LINE_MIN_INSN_LENGTH;
876
877             if (scaled <= 0x3F)
878               out_one (DW_CFA_advance_loc + scaled);
879             else if (delta <= 0xFF)
880               {
881                 out_one (DW_CFA_advance_loc1);
882                 out_one (delta);
883               }
884             else if (delta <= 0xFFFF)
885               {
886                 out_one (DW_CFA_advance_loc2);
887                 out_two (delta);
888               }
889             else
890               {
891                 out_one (DW_CFA_advance_loc4);
892                 out_four (delta);
893               }
894           }
895         else
896           {
897             expressionS exp;
898
899             exp.X_op = O_subtract;
900             exp.X_add_symbol = to;
901             exp.X_op_symbol = from;
902             exp.X_add_number = 0;
903
904             /* The code in ehopt.c expects that one byte of the encoding
905                is already allocated to the frag.  This comes from the way
906                that it scans the .eh_frame section looking first for the
907                .byte DW_CFA_advance_loc4.  */
908             frag_more (1);
909
910             frag_var (rs_cfa, 4, 0, DWARF2_LINE_MIN_INSN_LENGTH << 3,
911                       make_expr_symbol (&exp), frag_now_fix () - 1,
912                       (char *) frag_now);
913           }
914       }
915       break;
916
917     case DW_CFA_def_cfa:
918       offset = insn->u.ri.offset;
919       if (offset < 0)
920         {
921           out_one (DW_CFA_def_cfa_sf);
922           out_uleb128 (insn->u.ri.reg);
923           out_sleb128 (offset / DWARF2_CIE_DATA_ALIGNMENT);
924         }
925       else
926         {
927           out_one (DW_CFA_def_cfa);
928           out_uleb128 (insn->u.ri.reg);
929           out_uleb128 (offset);
930         }
931       break;
932
933     case DW_CFA_def_cfa_register:
934     case DW_CFA_undefined:
935     case DW_CFA_same_value:
936       out_one (insn->insn);
937       out_uleb128 (insn->u.r);
938       break;
939
940     case DW_CFA_def_cfa_offset:
941       offset = insn->u.i;
942       if (offset < 0)
943         {
944           out_one (DW_CFA_def_cfa_offset_sf);
945           out_sleb128 (offset / DWARF2_CIE_DATA_ALIGNMENT);
946         }
947       else
948         {
949           out_one (DW_CFA_def_cfa_offset);
950           out_uleb128 (offset);
951         }
952       break;
953
954     case DW_CFA_restore:
955       regno = insn->u.r;
956       if (regno <= 0x3F)
957         {
958           out_one (DW_CFA_restore + regno);
959         }
960       else
961         {
962           out_one (DW_CFA_restore_extended);
963           out_uleb128 (regno);
964         }
965       break;
966
967     case DW_CFA_offset:
968       regno = insn->u.ri.reg;
969       offset = insn->u.ri.offset / DWARF2_CIE_DATA_ALIGNMENT;
970       if (offset < 0)
971         {
972           out_one (DW_CFA_offset_extended_sf);
973           out_uleb128 (regno);
974           out_sleb128 (offset);
975         }
976       else if (regno <= 0x3F)
977         {
978           out_one (DW_CFA_offset + regno);
979           out_uleb128 (offset);
980         }
981       else
982         {
983           out_one (DW_CFA_offset_extended);
984           out_uleb128 (regno);
985           out_uleb128 (offset);
986         }
987       break;
988
989     case DW_CFA_register:
990       out_one (DW_CFA_register);
991       out_uleb128 (insn->u.rr.reg1);
992       out_uleb128 (insn->u.rr.reg2);
993       break;
994
995     case DW_CFA_remember_state:
996     case DW_CFA_restore_state:
997       out_one (insn->insn);
998       break;
999
1000     case DW_CFA_GNU_window_save:
1001       out_one (DW_CFA_GNU_window_save);
1002       break;
1003
1004     case CFI_escape:
1005       {
1006         struct cfi_escape_data *e;
1007         for (e = insn->u.esc; e ; e = e->next)
1008           emit_expr (&e->exp, 1);
1009         break;
1010       }
1011
1012     default:
1013       abort ();
1014     }
1015 }
1016
1017 static offsetT
1018 encoding_size (unsigned char encoding)
1019 {
1020   if (encoding == DW_EH_PE_omit)
1021     return 0;
1022   switch (encoding & 0x7)
1023     {
1024     case 0:
1025       return bfd_get_arch_size (stdoutput) == 64 ? 8 : 4;
1026     case DW_EH_PE_udata2:
1027       return 2;
1028     case DW_EH_PE_udata4:
1029       return 4;
1030     case DW_EH_PE_udata8:
1031       return 8;
1032     default:
1033       abort ();
1034     }
1035 }
1036
1037 static void
1038 output_cie (struct cie_entry *cie)
1039 {
1040   symbolS *after_size_address, *end_address;
1041   expressionS exp;
1042   struct cfi_insn_data *i;
1043   offsetT augmentation_size;
1044
1045   cie->start_address = symbol_temp_new_now ();
1046   after_size_address = symbol_temp_make ();
1047   end_address = symbol_temp_make ();
1048
1049   exp.X_op = O_subtract;
1050   exp.X_add_symbol = end_address;
1051   exp.X_op_symbol = after_size_address;
1052   exp.X_add_number = 0;
1053
1054   emit_expr (&exp, 4);                          /* Length.  */
1055   symbol_set_value_now (after_size_address);
1056   out_four (0);                                 /* CIE id.  */
1057   out_one (DW_CIE_VERSION);                     /* Version.  */
1058   out_one ('z');                                /* Augmentation.  */
1059   if (cie->per_encoding != DW_EH_PE_omit)
1060     out_one ('P');
1061   if (cie->lsda_encoding != DW_EH_PE_omit)
1062     out_one ('L');
1063   out_one ('R');
1064   if (cie->signal_frame)
1065     out_one ('S');
1066   out_one (0);
1067   out_uleb128 (DWARF2_LINE_MIN_INSN_LENGTH);    /* Code alignment.  */
1068   out_sleb128 (DWARF2_CIE_DATA_ALIGNMENT);      /* Data alignment.  */
1069   if (DW_CIE_VERSION == 1)                      /* Return column.  */
1070     out_one (cie->return_column);
1071   else
1072     out_uleb128 (cie->return_column);
1073   augmentation_size = 1 + (cie->lsda_encoding != DW_EH_PE_omit);
1074   if (cie->per_encoding != DW_EH_PE_omit)
1075     augmentation_size += 1 + encoding_size (cie->per_encoding);
1076   out_uleb128 (augmentation_size);              /* Augmentation size.  */
1077   if (cie->per_encoding != DW_EH_PE_omit)
1078     {
1079       offsetT size = encoding_size (cie->per_encoding);
1080       out_one (cie->per_encoding);
1081       exp = cie->personality;
1082       if ((cie->per_encoding & 0x70) == DW_EH_PE_pcrel)
1083         {
1084 #ifdef DIFF_EXPR_OK
1085           exp.X_op = O_subtract;
1086           exp.X_op_symbol = symbol_temp_new_now ();
1087           emit_expr (&exp, size);
1088 #elif defined (tc_cfi_emit_pcrel_expr)
1089           tc_cfi_emit_pcrel_expr (&exp, size);
1090 #else
1091           abort ();
1092 #endif
1093         }
1094       else
1095         emit_expr (&exp, size);
1096     }
1097   if (cie->lsda_encoding != DW_EH_PE_omit)
1098     out_one (cie->lsda_encoding);
1099 #if defined DIFF_EXPR_OK || defined tc_cfi_emit_pcrel_expr
1100   out_one (DW_EH_PE_pcrel | DW_EH_PE_sdata4);
1101 #else
1102   out_one (DW_EH_PE_sdata4);
1103 #endif
1104
1105   if (cie->first)
1106     for (i = cie->first; i != cie->last; i = i->next)
1107       output_cfi_insn (i);
1108
1109   frag_align (2, DW_CFA_nop, 0);
1110   symbol_set_value_now (end_address);
1111 }
1112
1113 static void
1114 output_fde (struct fde_entry *fde, struct cie_entry *cie,
1115             struct cfi_insn_data *first, int align)
1116 {
1117   symbolS *after_size_address, *end_address;
1118   expressionS exp;
1119   offsetT augmentation_size;
1120
1121   after_size_address = symbol_temp_make ();
1122   end_address = symbol_temp_make ();
1123
1124   exp.X_op = O_subtract;
1125   exp.X_add_symbol = end_address;
1126   exp.X_op_symbol = after_size_address;
1127   exp.X_add_number = 0;
1128   emit_expr (&exp, 4);                          /* Length.  */
1129   symbol_set_value_now (after_size_address);
1130
1131   exp.X_add_symbol = after_size_address;
1132   exp.X_op_symbol = cie->start_address;
1133   emit_expr (&exp, 4);                          /* CIE offset.  */
1134
1135 #ifdef DIFF_EXPR_OK
1136   exp.X_add_symbol = fde->start_address;
1137   exp.X_op_symbol = symbol_temp_new_now ();
1138   emit_expr (&exp, 4);                          /* Code offset.  */
1139 #else
1140   exp.X_op = O_symbol;
1141   exp.X_add_symbol = fde->start_address;
1142   exp.X_op_symbol = NULL;
1143 #ifdef tc_cfi_emit_pcrel_expr
1144   tc_cfi_emit_pcrel_expr (&exp, 4);             /* Code offset.  */
1145 #else
1146   emit_expr (&exp, 4);                          /* Code offset.  */
1147 #endif
1148   exp.X_op = O_subtract;
1149 #endif
1150
1151   exp.X_add_symbol = fde->end_address;
1152   exp.X_op_symbol = fde->start_address;         /* Code length.  */
1153   emit_expr (&exp, 4);
1154
1155   augmentation_size = encoding_size (fde->lsda_encoding);
1156   out_uleb128 (augmentation_size);              /* Augmentation size.  */
1157
1158   if (fde->lsda_encoding != DW_EH_PE_omit)
1159     {
1160       exp = fde->lsda;
1161       if ((fde->lsda_encoding & 0x70) == DW_EH_PE_pcrel)
1162         {
1163 #ifdef DIFF_EXPR_OK
1164           exp.X_op = O_subtract;
1165           exp.X_op_symbol = symbol_temp_new_now ();
1166           emit_expr (&exp, augmentation_size);
1167 #elif defined (tc_cfi_emit_pcrel_expr)
1168           tc_cfi_emit_pcrel_expr (&exp, augmentation_size);
1169 #else
1170           abort ();
1171 #endif
1172         }
1173       else
1174         emit_expr (&exp, augmentation_size);
1175     }
1176
1177   for (; first; first = first->next)
1178     output_cfi_insn (first);
1179
1180   frag_align (align, DW_CFA_nop, 0);
1181   symbol_set_value_now (end_address);
1182 }
1183
1184 static struct cie_entry *
1185 select_cie_for_fde (struct fde_entry *fde, struct cfi_insn_data **pfirst)
1186 {
1187   struct cfi_insn_data *i, *j;
1188   struct cie_entry *cie;
1189
1190   for (cie = cie_root; cie; cie = cie->next)
1191     {
1192       if (cie->return_column != fde->return_column
1193           || cie->signal_frame != fde->signal_frame
1194           || cie->per_encoding != fde->per_encoding
1195           || cie->lsda_encoding != fde->lsda_encoding)
1196         continue;
1197       if (cie->per_encoding != DW_EH_PE_omit)
1198         {
1199           if (cie->personality.X_op != fde->personality.X_op
1200               || cie->personality.X_add_number
1201                  != fde->personality.X_add_number)
1202             continue;
1203           switch (cie->personality.X_op)
1204             {
1205             case O_constant:
1206               if (cie->personality.X_unsigned != fde->personality.X_unsigned)
1207                 continue;
1208               break;
1209             case O_symbol:
1210               if (cie->personality.X_add_symbol
1211                   != fde->personality.X_add_symbol)
1212                 continue;
1213               break;
1214             default:
1215               abort ();
1216             }
1217         }
1218       for (i = cie->first, j = fde->data;
1219            i != cie->last && j != NULL;
1220            i = i->next, j = j->next)
1221         {
1222           if (i->insn != j->insn)
1223             goto fail;
1224           switch (i->insn)
1225             {
1226             case DW_CFA_advance_loc:
1227             case DW_CFA_remember_state:
1228               /* We reached the first advance/remember in the FDE,
1229                  but did not reach the end of the CIE list.  */
1230               goto fail;
1231
1232             case DW_CFA_offset:
1233             case DW_CFA_def_cfa:
1234               if (i->u.ri.reg != j->u.ri.reg)
1235                 goto fail;
1236               if (i->u.ri.offset != j->u.ri.offset)
1237                 goto fail;
1238               break;
1239
1240             case DW_CFA_register:
1241               if (i->u.rr.reg1 != j->u.rr.reg1)
1242                 goto fail;
1243               if (i->u.rr.reg2 != j->u.rr.reg2)
1244                 goto fail;
1245               break;
1246
1247             case DW_CFA_def_cfa_register:
1248             case DW_CFA_restore:
1249             case DW_CFA_undefined:
1250             case DW_CFA_same_value:
1251               if (i->u.r != j->u.r)
1252                 goto fail;
1253               break;
1254
1255             case DW_CFA_def_cfa_offset:
1256               if (i->u.i != j->u.i)
1257                 goto fail;
1258               break;
1259
1260             case CFI_escape:
1261               /* Don't bother matching these for now.  */
1262               goto fail;
1263
1264             default:
1265               abort ();
1266             }
1267         }
1268
1269       /* Success if we reached the end of the CIE list, and we've either
1270          run out of FDE entries or we've encountered an advance,
1271          remember, or escape.  */
1272       if (i == cie->last
1273           && (!j
1274               || j->insn == DW_CFA_advance_loc
1275               || j->insn == DW_CFA_remember_state
1276               || j->insn == CFI_escape))
1277         {
1278           *pfirst = j;
1279           return cie;
1280         }
1281
1282     fail:;
1283     }
1284
1285   cie = xmalloc (sizeof (struct cie_entry));
1286   cie->next = cie_root;
1287   cie_root = cie;
1288   cie->return_column = fde->return_column;
1289   cie->signal_frame = fde->signal_frame;
1290   cie->per_encoding = fde->per_encoding;
1291   cie->lsda_encoding = fde->lsda_encoding;
1292   cie->personality = fde->personality;
1293   cie->first = fde->data;
1294
1295   for (i = cie->first; i ; i = i->next)
1296     if (i->insn == DW_CFA_advance_loc
1297         || i->insn == DW_CFA_remember_state
1298         || i->insn == CFI_escape)
1299       break;
1300
1301   cie->last = i;
1302   *pfirst = i;
1303    
1304   output_cie (cie);
1305
1306   return cie;
1307 }
1308
1309 void
1310 cfi_finish (void)
1311 {
1312   segT cfi_seg;
1313   struct fde_entry *fde;
1314   int save_flag_traditional_format;
1315
1316   if (all_fde_data == 0)
1317     return;
1318
1319   /* Open .eh_frame section.  */
1320   cfi_seg = subseg_new (".eh_frame", 0);
1321   bfd_set_section_flags (stdoutput, cfi_seg,
1322                          SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_READONLY);
1323   subseg_set (cfi_seg, 0);
1324   record_alignment (cfi_seg, EH_FRAME_ALIGNMENT);
1325
1326   /* Make sure check_eh_frame doesn't do anything with our output.  */
1327   save_flag_traditional_format = flag_traditional_format;
1328   flag_traditional_format = 1;
1329
1330   for (fde = all_fde_data; fde ; fde = fde->next)
1331     {
1332       struct cfi_insn_data *first;
1333       struct cie_entry *cie;
1334
1335       if (fde->end_address == NULL)
1336         {
1337           as_bad (_("open CFI at the end of file; missing .cfi_endproc directive"));
1338           fde->end_address = fde->start_address;
1339         }
1340
1341       cie = select_cie_for_fde (fde, &first);
1342       output_fde (fde, cie, first, fde->next == NULL ? EH_FRAME_ALIGNMENT : 2);
1343     }
1344
1345   flag_traditional_format = save_flag_traditional_format;
1346 }
1347
1348 #else /* TARGET_USE_CFIPOP */
1349 void
1350 cfi_finish (void)
1351 {
1352 }
1353 #endif /* TARGET_USE_CFIPOP */