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