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>
5 This file is part of GAS, the GNU Assembler.
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)
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.
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
23 #include "dw2gencfi.h"
26 #ifdef TARGET_USE_CFIPOP
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
34 #ifndef EH_FRAME_ALIGNMENT
35 # define EH_FRAME_ALIGNMENT (bfd_get_arch_size (stdoutput) == 64 ? 3 : 2)
38 #ifndef tc_cfi_frame_initial_instructions
39 # define tc_cfi_frame_initial_instructions() ((void)0)
45 struct cfi_insn_data
*next
;
66 struct cfi_escape_data
{
67 struct cfi_escape_data
*next
;
75 struct fde_entry
*next
;
76 symbolS
*start_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
;
84 unsigned int return_column
;
85 unsigned int signal_frame
;
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
;
101 /* List of FDE entries. */
102 static struct fde_entry
*all_fde_data
;
103 static struct fde_entry
**last_fde_data
= &all_fde_data
;
105 /* List of CIEs so that they could be reused. */
106 static struct cie_entry
*cie_root
;
108 /* Stack of old CFI data, for save/restore. */
111 struct cfa_save_data
*next
;
115 /* Current open FDE entry. */
118 struct fde_entry
*cur_fde_data
;
119 symbolS
*last_address
;
120 offsetT cur_cfa_offset
;
121 struct cfa_save_data
*cfa_save_stack
;
124 /* Construct a new FDE structure and add it to the end of the fde list. */
126 static struct fde_entry
*
127 alloc_fde_entry (void)
129 struct fde_entry
*fde
= xcalloc (1, sizeof (struct fde_entry
));
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
;
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
;
144 /* The following functions are available for a backend to construct its
145 own unwind information, usually from legacy unwind directives. */
147 /* Construct a new INSN structure and add it to the end of the insn list
148 for the currently active FDE. */
150 static struct cfi_insn_data
*
151 alloc_cfi_insn_data (void)
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
;
156 *cur_fde_data
->last
= insn
;
157 cur_fde_data
->last
= &insn
->next
;
162 /* Construct a new FDE structure that begins at LABEL. */
165 cfi_new_fde (symbolS
*label
)
167 struct fde_entry
*fde
= alloc_fde_entry ();
168 fde
->start_address
= label
;
169 frchain_now
->frch_cfi_data
->last_address
= label
;
172 /* End the currently open FDE. */
175 cfi_end_fde (symbolS
*label
)
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
;
182 /* Set the return column for the current FDE. */
185 cfi_set_return_column (unsigned regno
)
187 frchain_now
->frch_cfi_data
->cur_fde_data
->return_column
= regno
;
190 /* Universal functions to store new instructions. */
193 cfi_add_CFA_insn(int insn
)
195 struct cfi_insn_data
*insn_ptr
= alloc_cfi_insn_data ();
197 insn_ptr
->insn
= insn
;
201 cfi_add_CFA_insn_reg (int insn
, unsigned regno
)
203 struct cfi_insn_data
*insn_ptr
= alloc_cfi_insn_data ();
205 insn_ptr
->insn
= insn
;
206 insn_ptr
->u
.r
= regno
;
210 cfi_add_CFA_insn_offset (int insn
, offsetT offset
)
212 struct cfi_insn_data
*insn_ptr
= alloc_cfi_insn_data ();
214 insn_ptr
->insn
= insn
;
215 insn_ptr
->u
.i
= offset
;
219 cfi_add_CFA_insn_reg_reg (int insn
, unsigned reg1
, unsigned reg2
)
221 struct cfi_insn_data
*insn_ptr
= alloc_cfi_insn_data ();
223 insn_ptr
->insn
= insn
;
224 insn_ptr
->u
.rr
.reg1
= reg1
;
225 insn_ptr
->u
.rr
.reg2
= reg2
;
229 cfi_add_CFA_insn_reg_offset (int insn
, unsigned regno
, offsetT offset
)
231 struct cfi_insn_data
*insn_ptr
= alloc_cfi_insn_data ();
233 insn_ptr
->insn
= insn
;
234 insn_ptr
->u
.ri
.reg
= regno
;
235 insn_ptr
->u
.ri
.offset
= offset
;
238 /* Add a CFI insn to advance the PC from the last address to LABEL. */
241 cfi_add_advance_loc (symbolS
*label
)
243 struct cfi_insn_data
*insn
= alloc_cfi_insn_data ();
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
;
249 frchain_now
->frch_cfi_data
->last_address
= label
;
252 /* Add a DW_CFA_offset record to the CFI data. */
255 cfi_add_CFA_offset (unsigned regno
, offsetT offset
)
257 unsigned int abs_data_align
;
259 assert (DWARF2_CIE_DATA_ALIGNMENT
!= 0);
260 cfi_add_CFA_insn_reg_offset (DW_CFA_offset
, regno
, offset
);
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
);
268 /* Add a DW_CFA_def_cfa record to the CFI data. */
271 cfi_add_CFA_def_cfa (unsigned regno
, offsetT offset
)
273 cfi_add_CFA_insn_reg_offset (DW_CFA_def_cfa
, regno
, offset
);
274 frchain_now
->frch_cfi_data
->cur_cfa_offset
= offset
;
277 /* Add a DW_CFA_register record to the CFI data. */
280 cfi_add_CFA_register (unsigned reg1
, unsigned reg2
)
282 cfi_add_CFA_insn_reg_reg (DW_CFA_register
, reg1
, reg2
);
285 /* Add a DW_CFA_def_cfa_register record to the CFI data. */
288 cfi_add_CFA_def_cfa_register (unsigned regno
)
290 cfi_add_CFA_insn_reg (DW_CFA_def_cfa_register
, regno
);
293 /* Add a DW_CFA_def_cfa_offset record to the CFI data. */
296 cfi_add_CFA_def_cfa_offset (offsetT offset
)
298 cfi_add_CFA_insn_offset (DW_CFA_def_cfa_offset
, offset
);
299 frchain_now
->frch_cfi_data
->cur_cfa_offset
= offset
;
303 cfi_add_CFA_restore (unsigned regno
)
305 cfi_add_CFA_insn_reg (DW_CFA_restore
, regno
);
309 cfi_add_CFA_undefined (unsigned regno
)
311 cfi_add_CFA_insn_reg (DW_CFA_undefined
, regno
);
315 cfi_add_CFA_same_value (unsigned regno
)
317 cfi_add_CFA_insn_reg (DW_CFA_same_value
, regno
);
321 cfi_add_CFA_remember_state (void)
323 struct cfa_save_data
*p
;
325 cfi_add_CFA_insn (DW_CFA_remember_state
);
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
;
334 cfi_add_CFA_restore_state (void)
336 struct cfa_save_data
*p
;
338 cfi_add_CFA_insn (DW_CFA_restore_state
);
340 p
= frchain_now
->frch_cfi_data
->cfa_save_stack
;
343 frchain_now
->frch_cfi_data
->cur_cfa_offset
= p
->cfa_offset
;
344 frchain_now
->frch_cfi_data
->cfa_save_stack
= p
->next
;
348 as_bad (_("CFI state restore without previous remember"));
352 /* Parse CFI assembler directives. */
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);
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
368 const pseudo_typeS cfi_pseudo_table
[] =
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 },
394 cfi_parse_separator (void)
397 if (*input_line_pointer
== ',')
398 input_line_pointer
++;
400 as_bad (_("missing separator"));
403 #ifndef tc_parse_to_dw2regnum
405 tc_parse_to_dw2regnum(expressionS
*exp
)
407 # ifdef tc_regname_to_dw2regnum
409 if (is_name_beginner (*input_line_pointer
)
410 || (*input_line_pointer
== '%'
411 && is_name_beginner (*++input_line_pointer
)))
415 name
= input_line_pointer
;
416 c
= get_symbol_end ();
418 exp
->X_op
= O_constant
;
419 exp
->X_add_number
= tc_regname_to_dw2regnum (name
);
421 *input_line_pointer
= c
;
425 expression_and_evaluate (exp
);
435 tc_parse_to_dw2regnum (&exp
);
440 regno
= exp
.X_add_number
;
450 as_bad (_("bad register expression"));
458 cfi_parse_const (void)
460 return get_absolute_expression ();
469 if (frchain_now
->frch_cfi_data
== NULL
)
471 as_bad (_("CFI instruction used without previous .cfi_startproc"));
472 ignore_rest_of_line ();
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
)
480 cfi_add_advance_loc (symbol_temp_new_now ());
485 reg1
= cfi_parse_reg ();
486 cfi_parse_separator ();
487 offset
= cfi_parse_const ();
488 cfi_add_CFA_offset (reg1
, 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
);
500 reg1
= cfi_parse_reg ();
501 cfi_parse_separator ();
502 offset
= cfi_parse_const ();
503 cfi_add_CFA_def_cfa (reg1
, offset
);
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
);
513 case DW_CFA_def_cfa_register
:
514 reg1
= cfi_parse_reg ();
515 cfi_add_CFA_def_cfa_register (reg1
);
518 case DW_CFA_def_cfa_offset
:
519 offset
= cfi_parse_const ();
520 cfi_add_CFA_def_cfa_offset (offset
);
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
532 reg1
= cfi_parse_reg ();
533 cfi_add_CFA_restore (reg1
);
535 if (*input_line_pointer
!= ',')
537 ++input_line_pointer
;
541 case DW_CFA_undefined
:
544 reg1
= cfi_parse_reg ();
545 cfi_add_CFA_undefined (reg1
);
547 if (*input_line_pointer
!= ',')
549 ++input_line_pointer
;
553 case DW_CFA_same_value
:
554 reg1
= cfi_parse_reg ();
555 cfi_add_CFA_same_value (reg1
);
558 case CFI_return_column
:
559 reg1
= cfi_parse_reg ();
560 cfi_set_return_column (reg1
);
563 case DW_CFA_remember_state
:
564 cfi_add_CFA_remember_state ();
567 case DW_CFA_restore_state
:
568 cfi_add_CFA_restore_state ();
571 case DW_CFA_GNU_window_save
:
572 cfi_add_CFA_insn (DW_CFA_GNU_window_save
);
575 case CFI_signal_frame
:
576 frchain_now
->frch_cfi_data
->cur_fde_data
->signal_frame
= 1;
583 demand_empty_rest_of_line ();
587 dot_cfi_escape (int ignored ATTRIBUTE_UNUSED
)
589 struct cfi_escape_data
*head
, **tail
, *e
;
590 struct cfi_insn_data
*insn
;
592 if (frchain_now
->frch_cfi_data
== NULL
)
594 as_bad (_("CFI instruction used without previous .cfi_startproc"));
595 ignore_rest_of_line ();
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
)
603 cfi_add_advance_loc (symbol_temp_new_now ());
608 e
= xmalloc (sizeof (*e
));
609 do_parse_cons_expression (&e
->exp
, 1);
613 while (*input_line_pointer
++ == ',');
616 insn
= alloc_cfi_insn_data ();
617 insn
->insn
= CFI_escape
;
620 --input_line_pointer
;
621 demand_empty_rest_of_line ();
625 dot_cfi_personality (int ignored ATTRIBUTE_UNUSED
)
627 struct fde_entry
*fde
;
630 if (frchain_now
->frch_cfi_data
== NULL
)
632 as_bad (_("CFI instruction used without previous .cfi_startproc"));
633 ignore_rest_of_line ();
637 fde
= frchain_now
->frch_cfi_data
->cur_fde_data
;
638 encoding
= get_absolute_expression ();
639 if (encoding
== DW_EH_PE_omit
)
641 demand_empty_rest_of_line ();
642 fde
->per_encoding
= encoding
;
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
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
)
656 as_bad (_("invalid or unsupported encoding in .cfi_personality"));
657 ignore_rest_of_line ();
661 if (*input_line_pointer
++ != ',')
663 as_bad (_(".cfi_personality requires encoding and symbol arguments"));
664 ignore_rest_of_line ();
668 expression_and_evaluate (&fde
->personality
);
669 switch (fde
->personality
.X_op
)
674 if ((encoding
& 0x70) == DW_EH_PE_pcrel
)
675 encoding
= DW_EH_PE_omit
;
678 encoding
= DW_EH_PE_omit
;
682 fde
->per_encoding
= encoding
;
684 if (encoding
== DW_EH_PE_omit
)
686 as_bad (_("wrong second argument to .cfi_personality"));
687 ignore_rest_of_line ();
691 demand_empty_rest_of_line ();
695 dot_cfi_lsda (int ignored ATTRIBUTE_UNUSED
)
697 struct fde_entry
*fde
;
700 if (frchain_now
->frch_cfi_data
== NULL
)
702 as_bad (_("CFI instruction used without previous .cfi_startproc"));
703 ignore_rest_of_line ();
707 fde
= frchain_now
->frch_cfi_data
->cur_fde_data
;
708 encoding
= get_absolute_expression ();
709 if (encoding
== DW_EH_PE_omit
)
711 demand_empty_rest_of_line ();
712 fde
->lsda_encoding
= encoding
;
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
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
)
726 as_bad (_("invalid or unsupported encoding in .cfi_lsda"));
727 ignore_rest_of_line ();
731 if (*input_line_pointer
++ != ',')
733 as_bad (_(".cfi_lsda requires encoding and symbol arguments"));
734 ignore_rest_of_line ();
738 fde
->lsda_encoding
= encoding
;
740 expression_and_evaluate (&fde
->lsda
);
741 switch (fde
->lsda
.X_op
)
746 if ((encoding
& 0x70) == DW_EH_PE_pcrel
)
747 encoding
= DW_EH_PE_omit
;
750 encoding
= DW_EH_PE_omit
;
754 fde
->lsda_encoding
= encoding
;
756 if (encoding
== DW_EH_PE_omit
)
758 as_bad (_("wrong second argument to .cfi_lsda"));
759 ignore_rest_of_line ();
763 demand_empty_rest_of_line ();
767 dot_cfi_startproc (int ignored ATTRIBUTE_UNUSED
)
771 if (frchain_now
->frch_cfi_data
!= NULL
)
773 as_bad (_("previous CFI entry not closed (missing .cfi_endproc)"));
774 ignore_rest_of_line ();
778 cfi_new_fde (symbol_temp_new_now ());
781 if (is_name_beginner (*input_line_pointer
))
785 name
= input_line_pointer
;
786 c
= get_symbol_end ();
788 if (strcmp (name
, "simple") == 0)
791 *input_line_pointer
= c
;
794 input_line_pointer
= name
;
796 demand_empty_rest_of_line ();
798 frchain_now
->frch_cfi_data
->cur_cfa_offset
= 0;
800 tc_cfi_frame_initial_instructions ();
804 dot_cfi_endproc (int ignored ATTRIBUTE_UNUSED
)
806 if (frchain_now
->frch_cfi_data
== NULL
)
808 as_bad (_(".cfi_endproc without corresponding .cfi_startproc"));
809 ignore_rest_of_line ();
813 cfi_end_fde (symbol_temp_new_now ());
815 demand_empty_rest_of_line ();
819 /* Emit a single byte into the current segment. */
824 FRAG_APPEND_1_CHAR (byte
);
827 /* Emit a two-byte word into the current segment. */
832 md_number_to_chars (frag_more (2), data
, 2);
835 /* Emit a four byte word into the current segment. */
840 md_number_to_chars (frag_more (4), data
, 4);
843 /* Emit an unsigned "little-endian base 128" number. */
846 out_uleb128 (addressT value
)
848 output_leb128 (frag_more (sizeof_leb128 (value
, 0)), value
, 0);
851 /* Emit an unsigned "little-endian base 128" number. */
854 out_sleb128 (offsetT value
)
856 output_leb128 (frag_more (sizeof_leb128 (value
, 1)), value
, 1);
860 output_cfi_insn (struct cfi_insn_data
*insn
)
867 case DW_CFA_advance_loc
:
869 symbolS
*from
= insn
->u
.ll
.lab1
;
870 symbolS
*to
= insn
->u
.ll
.lab2
;
872 if (symbol_get_frag (to
) == symbol_get_frag (from
))
874 addressT delta
= S_GET_VALUE (to
) - S_GET_VALUE (from
);
875 addressT scaled
= delta
/ DWARF2_LINE_MIN_INSN_LENGTH
;
878 out_one (DW_CFA_advance_loc
+ scaled
);
879 else if (delta
<= 0xFF)
881 out_one (DW_CFA_advance_loc1
);
884 else if (delta
<= 0xFFFF)
886 out_one (DW_CFA_advance_loc2
);
891 out_one (DW_CFA_advance_loc4
);
899 exp
.X_op
= O_subtract
;
900 exp
.X_add_symbol
= to
;
901 exp
.X_op_symbol
= from
;
902 exp
.X_add_number
= 0;
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. */
910 frag_var (rs_cfa
, 4, 0, DWARF2_LINE_MIN_INSN_LENGTH
<< 3,
911 make_expr_symbol (&exp
), frag_now_fix () - 1,
918 offset
= insn
->u
.ri
.offset
;
921 out_one (DW_CFA_def_cfa_sf
);
922 out_uleb128 (insn
->u
.ri
.reg
);
923 out_sleb128 (offset
/ DWARF2_CIE_DATA_ALIGNMENT
);
927 out_one (DW_CFA_def_cfa
);
928 out_uleb128 (insn
->u
.ri
.reg
);
929 out_uleb128 (offset
);
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
);
940 case DW_CFA_def_cfa_offset
:
944 out_one (DW_CFA_def_cfa_offset_sf
);
945 out_sleb128 (offset
/ DWARF2_CIE_DATA_ALIGNMENT
);
949 out_one (DW_CFA_def_cfa_offset
);
950 out_uleb128 (offset
);
958 out_one (DW_CFA_restore
+ regno
);
962 out_one (DW_CFA_restore_extended
);
968 regno
= insn
->u
.ri
.reg
;
969 offset
= insn
->u
.ri
.offset
/ DWARF2_CIE_DATA_ALIGNMENT
;
972 out_one (DW_CFA_offset_extended_sf
);
974 out_sleb128 (offset
);
976 else if (regno
<= 0x3F)
978 out_one (DW_CFA_offset
+ regno
);
979 out_uleb128 (offset
);
983 out_one (DW_CFA_offset_extended
);
985 out_uleb128 (offset
);
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
);
995 case DW_CFA_remember_state
:
996 case DW_CFA_restore_state
:
997 out_one (insn
->insn
);
1000 case DW_CFA_GNU_window_save
:
1001 out_one (DW_CFA_GNU_window_save
);
1006 struct cfi_escape_data
*e
;
1007 for (e
= insn
->u
.esc
; e
; e
= e
->next
)
1008 emit_expr (&e
->exp
, 1);
1018 encoding_size (unsigned char encoding
)
1020 if (encoding
== DW_EH_PE_omit
)
1022 switch (encoding
& 0x7)
1025 return bfd_get_arch_size (stdoutput
) == 64 ? 8 : 4;
1026 case DW_EH_PE_udata2
:
1028 case DW_EH_PE_udata4
:
1030 case DW_EH_PE_udata8
:
1038 output_cie (struct cie_entry
*cie
)
1040 symbolS
*after_size_address
, *end_address
;
1042 struct cfi_insn_data
*i
;
1043 offsetT augmentation_size
;
1045 cie
->start_address
= symbol_temp_new_now ();
1046 after_size_address
= symbol_temp_make ();
1047 end_address
= symbol_temp_make ();
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;
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
)
1061 if (cie
->lsda_encoding
!= DW_EH_PE_omit
)
1064 if (cie
->signal_frame
)
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
);
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
)
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
)
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
);
1095 emit_expr (&exp
, size
);
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
);
1102 out_one (DW_EH_PE_sdata4
);
1106 for (i
= cie
->first
; i
!= cie
->last
; i
= i
->next
)
1107 output_cfi_insn (i
);
1109 frag_align (2, DW_CFA_nop
, 0);
1110 symbol_set_value_now (end_address
);
1114 output_fde (struct fde_entry
*fde
, struct cie_entry
*cie
,
1115 struct cfi_insn_data
*first
, int align
)
1117 symbolS
*after_size_address
, *end_address
;
1119 offsetT augmentation_size
;
1121 after_size_address
= symbol_temp_make ();
1122 end_address
= symbol_temp_make ();
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
);
1131 exp
.X_add_symbol
= after_size_address
;
1132 exp
.X_op_symbol
= cie
->start_address
;
1133 emit_expr (&exp
, 4); /* CIE offset. */
1136 exp
.X_add_symbol
= fde
->start_address
;
1137 exp
.X_op_symbol
= symbol_temp_new_now ();
1138 emit_expr (&exp
, 4); /* Code offset. */
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. */
1146 emit_expr (&exp
, 4); /* Code offset. */
1148 exp
.X_op
= O_subtract
;
1151 exp
.X_add_symbol
= fde
->end_address
;
1152 exp
.X_op_symbol
= fde
->start_address
; /* Code length. */
1153 emit_expr (&exp
, 4);
1155 augmentation_size
= encoding_size (fde
->lsda_encoding
);
1156 out_uleb128 (augmentation_size
); /* Augmentation size. */
1158 if (fde
->lsda_encoding
!= DW_EH_PE_omit
)
1161 if ((fde
->lsda_encoding
& 0x70) == DW_EH_PE_pcrel
)
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
);
1174 emit_expr (&exp
, augmentation_size
);
1177 for (; first
; first
= first
->next
)
1178 output_cfi_insn (first
);
1180 frag_align (align
, DW_CFA_nop
, 0);
1181 symbol_set_value_now (end_address
);
1184 static struct cie_entry
*
1185 select_cie_for_fde (struct fde_entry
*fde
, struct cfi_insn_data
**pfirst
)
1187 struct cfi_insn_data
*i
, *j
;
1188 struct cie_entry
*cie
;
1190 for (cie
= cie_root
; cie
; cie
= cie
->next
)
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
)
1197 if (cie
->per_encoding
!= DW_EH_PE_omit
)
1199 if (cie
->personality
.X_op
!= fde
->personality
.X_op
1200 || cie
->personality
.X_add_number
1201 != fde
->personality
.X_add_number
)
1203 switch (cie
->personality
.X_op
)
1206 if (cie
->personality
.X_unsigned
!= fde
->personality
.X_unsigned
)
1210 if (cie
->personality
.X_add_symbol
1211 != fde
->personality
.X_add_symbol
)
1218 for (i
= cie
->first
, j
= fde
->data
;
1219 i
!= cie
->last
&& j
!= NULL
;
1220 i
= i
->next
, j
= j
->next
)
1222 if (i
->insn
!= j
->insn
)
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. */
1233 case DW_CFA_def_cfa
:
1234 if (i
->u
.ri
.reg
!= j
->u
.ri
.reg
)
1236 if (i
->u
.ri
.offset
!= j
->u
.ri
.offset
)
1240 case DW_CFA_register
:
1241 if (i
->u
.rr
.reg1
!= j
->u
.rr
.reg1
)
1243 if (i
->u
.rr
.reg2
!= j
->u
.rr
.reg2
)
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
)
1255 case DW_CFA_def_cfa_offset
:
1256 if (i
->u
.i
!= j
->u
.i
)
1261 /* Don't bother matching these for now. */
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. */
1274 || j
->insn
== DW_CFA_advance_loc
1275 || j
->insn
== DW_CFA_remember_state
1276 || j
->insn
== CFI_escape
))
1285 cie
= xmalloc (sizeof (struct cie_entry
));
1286 cie
->next
= cie_root
;
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
;
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
)
1313 struct fde_entry
*fde
;
1314 int save_flag_traditional_format
;
1316 if (all_fde_data
== 0)
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
);
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;
1330 for (fde
= all_fde_data
; fde
; fde
= fde
->next
)
1332 struct cfi_insn_data
*first
;
1333 struct cie_entry
*cie
;
1335 if (fde
->end_address
== NULL
)
1337 as_bad (_("open CFI at the end of file; missing .cfi_endproc directive"));
1338 fde
->end_address
= fde
->start_address
;
1341 cie
= select_cie_for_fde (fde
, &first
);
1342 output_fde (fde
, cie
, first
, fde
->next
== NULL
? EH_FRAME_ALIGNMENT
: 2);
1345 flag_traditional_format
= save_flag_traditional_format
;
1348 #else /* TARGET_USE_CFIPOP */
1353 #endif /* TARGET_USE_CFIPOP */