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