Index: doc/as.texinfo =================================================================== RCS file: /cvs/src/src/gas/doc/as.texinfo,v retrieving revision 1.266 diff -p -u -r1.266 as.texinfo --- doc/as.texinfo 29 Apr 2013 13:38:58 -0000 1.266 +++ doc/as.texinfo 31 May 2013 17:24:20 -0000 @@ -4479,6 +4479,9 @@ if @var{section_list} is @code{.debug_fr To emit both use @code{.eh_frame, .debug_frame}. The default if this directive is not used is @code{.cfi_sections .eh_frame}. +On targets that support compact unwinding tables these can be generated +by specifying @code{.eh_frame_header} instead of @code{.eh_frame}. + @section @code{.cfi_startproc [simple]} @cindex @code{cfi_startproc} directive @code{.cfi_startproc} is used at the beginning of each function that @@ -4514,6 +4517,23 @@ argument is not present, otherwise secon or a symbol name. The default after @code{.cfi_startproc} is @code{.cfi_lsda 0xff}, no LSDA. +@section @code{.cfi_inline_lsda} [@var{align}] +@code{.cfi_inline_lsda} marks the start of a LSDA data section and +switches to the corresponding @code{.gnu.extab} section. +It must be preceded by a CFI block containing a @code{.cfi_lsda} directive and +is only valid when generating compact EH frames (i.e. +with @code{.cfi_sections eh_frame_entry}. + +If a compact encoding is being used then the table header and unwinding +opcodes will be generated at this point, so that they are immediately +followed by the LSDA data. The symbol referenced by the @code{.cfi_lsda} +directive should still be defined in case a fallback FDE based encoding +is used. + +The optional @var{align} argument specifies the alignment required. +The alignment is specified as a power of two, as with the +@code{.p2align} directive. + @section @code{.cfi_def_cfa @var{register}, @var{offset}} @code{.cfi_def_cfa} defines a rule for computing CFA as: @i{take address from @var{register} and add @var{offset} to it}. Index: dw2gencfi.c =================================================================== RCS file: /cvs/src/src/gas/dw2gencfi.c,v retrieving revision 1.58 diff -p -u -r1.58 dw2gencfi.c --- dw2gencfi.c 10 Jan 2013 19:51:54 -0000 1.58 +++ dw2gencfi.c 31 May 2013 17:24:20 -0000 @@ -76,6 +76,8 @@ # define tc_cfi_endproc(fde) ((void) (fde)) #endif +#define EH_FRAME_LINKONCE (SUPPORT_FRAME_LINKONCE || compact_eh) + #ifndef DWARF2_FORMAT #define DWARF2_FORMAT(SEC) dwarf2_format_32bit #endif @@ -84,7 +86,7 @@ #define DWARF2_ADDR_SIZE(bfd) (bfd_arch_bits_per_address (bfd) / 8) #endif -#if SUPPORT_FRAME_LINKONCE +#if MULTIPLE_FRAME_SECTIONS #define CUR_SEG(structp) structp->cur_seg #define SET_CUR_SEG(structp, seg) structp->cur_seg = seg #define HANDLED(structp) structp->handled @@ -96,6 +98,11 @@ #define SET_HANDLED(structp, val) (void) (0 && val) #endif +#ifndef tc_cfi_special_encoding +#define tc_cfi_emit_expr(exp, enc) (void) 0 +#define tc_cfi_special_encoding(e) 0 +#endif + /* Private segment collection list. */ struct dwcfi_seg_list { @@ -104,7 +111,11 @@ struct dwcfi_seg_list char * seg_name; }; -#define FRAME_NAME ".eh_frame" +#ifdef SUPPORT_COMPACT_EH +static bfd_boolean compact_eh; +#else +#define compact_eh 0 +#endif static struct hash_control *dwcfi_hash; @@ -129,7 +140,12 @@ get_debugseg_name (segT seg, const char dot = strchr (name + 1, '.'); if (!dollar && !dot) - name = ""; + { + if (compact_eh && strcmp (name, ".text") != 0) + return concat (base_name, ".", name, NULL); + + name = ""; + } else if (!dollar) name = dot; else if (!dot) @@ -161,6 +177,9 @@ alloc_debugseg_item (segT seg, int subse static segT is_now_linkonce_segment (void) { + if (compact_eh) + return now_seg; + if ((bfd_get_section_flags (stdoutput, now_seg) & (SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD | SEC_LINK_DUPLICATES_ONE_ONLY | SEC_LINK_DUPLICATES_SAME_SIZE @@ -180,7 +199,11 @@ make_debug_seg (segT cseg, char *name, i segT r; flagword flags; +#ifdef tc_make_debug_seg + r = tc_make_debug_seg (cseg, name); +#else r = subseg_new (name, 0); +#endif /* Check if code segment is marked as linked once. */ if (!cseg) @@ -273,12 +296,13 @@ struct cfi_escape_data struct cie_entry { struct cie_entry *next; -#if SUPPORT_FRAME_LINKONCE +#if MULTIPLE_FRAME_SECTIONS segT cur_seg; #endif symbolS *start_address; unsigned int return_column; unsigned int signal_frame; + unsigned char fde_encoding; unsigned char per_encoding; unsigned char lsda_encoding; expressionS personality; @@ -551,6 +575,7 @@ static void dot_cfi_endproc (int); static void dot_cfi_personality (int); static void dot_cfi_lsda (int); static void dot_cfi_val_encoded_addr (int); +static void dot_cfi_inline_lsda (int); const pseudo_typeS cfi_pseudo_table[] = { @@ -576,6 +601,7 @@ const pseudo_typeS cfi_pseudo_table[] = { "cfi_personality", dot_cfi_personality, 0 }, { "cfi_lsda", dot_cfi_lsda, 0 }, { "cfi_val_encoded_addr", dot_cfi_val_encoded_addr, 0 }, + { "cfi_inline_lsda", dot_cfi_inline_lsda, 0 }, { NULL, NULL, 0 } }; @@ -833,14 +859,15 @@ dot_cfi_personality (int ignored ATTRIBU } if ((encoding & 0xff) != encoding - || ((encoding & 0x70) != 0 + || ((((encoding & 0x70) != 0 #if CFI_DIFF_EXPR_OK || defined tc_cfi_emit_pcrel_expr - && (encoding & 0x70) != DW_EH_PE_pcrel + && (encoding & 0x70) != DW_EH_PE_pcrel #endif ) /* leb128 can be handled, but does something actually need it? */ - || (encoding & 7) == DW_EH_PE_uleb128 - || (encoding & 7) > DW_EH_PE_udata8) + || (encoding & 7) == DW_EH_PE_uleb128 + || (encoding & 7) > DW_EH_PE_udata8) + && !tc_cfi_special_encoding (encoding))) { as_bad (_("invalid or unsupported encoding in .cfi_personality")); ignore_rest_of_line (); @@ -903,14 +930,15 @@ dot_cfi_lsda (int ignored ATTRIBUTE_UNUS } if ((encoding & 0xff) != encoding - || ((encoding & 0x70) != 0 + || ((((encoding & 0x70) != 0 #if CFI_DIFF_LSDA_OK || defined tc_cfi_emit_pcrel_expr - && (encoding & 0x70) != DW_EH_PE_pcrel + && (encoding & 0x70) != DW_EH_PE_pcrel #endif - ) + ) /* leb128 can be handled, but does something actually need it? */ - || (encoding & 7) == DW_EH_PE_uleb128 - || (encoding & 7) > DW_EH_PE_udata8) + || (encoding & 7) == DW_EH_PE_uleb128 + || (encoding & 7) > DW_EH_PE_udata8) + && !tc_cfi_special_encoding (encoding))) { as_bad (_("invalid or unsupported encoding in .cfi_lsda")); ignore_rest_of_line (); @@ -1022,6 +1050,8 @@ dot_cfi_val_encoded_addr (int ignored AT #define CFI_EMIT_debug_frame (1 << 1) #define CFI_EMIT_target (1 << 2) static int cfi_sections = CFI_EMIT_eh_frame; +static int all_cfi_sections = 0; +static struct fde_entry *last_fde; static void dot_cfi_sections (int ignored ATTRIBUTE_UNUSED) @@ -1042,6 +1072,13 @@ dot_cfi_sections (int ignored ATTRIBUTE_ sections |= CFI_EMIT_eh_frame; else if (strncmp (name, ".debug_frame", sizeof ".debug_frame") == 0) sections |= CFI_EMIT_debug_frame; +#if SUPPORT_COMPACT_EH + else if (strncmp (name, ".eh_frame_entry", sizeof ".eh_frame_entry") == 0) + { + compact_eh = TRUE; + sections |= CFI_EMIT_eh_frame | CFI_EMIT_target; + } +#endif #ifdef tc_cfi_section_name else if (strcmp (name, tc_cfi_section_name) == 0) sections |= CFI_EMIT_target; @@ -1105,6 +1142,8 @@ dot_cfi_startproc (int ignored ATTRIBUTE } demand_empty_rest_of_line (); + all_cfi_sections |= cfi_sections; + frchain_now->frch_cfi_data->cur_fde_data->sections = cfi_sections; frchain_now->frch_cfi_data->cur_cfa_offset = 0; if (!simple) tc_cfi_frame_initial_instructions (); @@ -1116,8 +1155,6 @@ dot_cfi_startproc (int ignored ATTRIBUTE static void dot_cfi_endproc (int ignored ATTRIBUTE_UNUSED) { - struct fde_entry *fde; - if (frchain_now->frch_cfi_data == NULL) { as_bad (_(".cfi_endproc without corresponding .cfi_startproc")); @@ -1125,16 +1162,147 @@ dot_cfi_endproc (int ignored ATTRIBUTE_U return; } - fde = frchain_now->frch_cfi_data->cur_fde_data; + last_fde = frchain_now->frch_cfi_data->cur_fde_data; cfi_end_fde (symbol_temp_new_now ()); demand_empty_rest_of_line (); - if ((cfi_sections & CFI_EMIT_target) != 0) - tc_cfi_endproc (fde); + if ((cfi_sections & CFI_EMIT_target) != 0 + || (compact_eh && (cfi_sections & CFI_EMIT_eh_frame) != 0)) + tc_cfi_endproc (last_fde); } +static segT +get_cfi_seg (segT cseg, const char *base, flagword flags, int align) +{ + if (SUPPORT_FRAME_LINKONCE || ((flags & SEC_DEBUGGING) == 0 && compact_eh)) + { + struct dwcfi_seg_list *l; + + l = dwcfi_hash_find_or_make (cseg, base, flags); + + cseg = l->seg; + subseg_set (cseg, l->subseg); + } + else + { + cseg = subseg_new (base, 0); + bfd_set_section_flags (stdoutput, cseg, flags); + } + record_alignment (cseg, align); + return cseg; +} + +#if SUPPORT_COMPACT_EH +static void +output_compact_unwind_data (struct fde_entry *fde, int align) +{ + int data_size = fde->eh_data_size + 2; + int amask; + char *p; + char *end; + + fde->eh_loc = symbol_temp_new_now (); + if (fde->per_encoding != DW_EH_PE_omit) + data_size += 4; + + amask = (1 << align) - 1; + data_size = (data_size + amask) & ~amask; + p = frag_more (data_size); + end = p + data_size - 1; + if (fde->per_encoding != DW_EH_PE_omit) + { + *(p++) = 0; + md_number_to_chars (p, 0, 4); + tc_cfi_fix_eh_ref (p, &fde->personality); + p += 4; + } + else + { + *(p++) = 1; + } + + memcpy (p, fde->eh_data, fde->eh_data_size); + p += fde->eh_data_size; + while (p != end) + *(p++) = 0x5f; + + *(p++) = 0x5c; + fde->eh_header_type = EH_COMPACT_OUTLINE_DONE; +} + +static void +dot_cfi_inline_lsda (int ignored ATTRIBUTE_UNUSED) +{ + segT cfi_seg, ccseg; + int align; + long max_alignment = 28; + + if (!last_fde) + { + as_bad (_("unexpected .cfi_inline_lsda")); + ignore_rest_of_line (); + return; + } + + if (!compact_eh + || (last_fde->sections & CFI_EMIT_eh_frame) == 0 + || (last_fde->eh_header_type != EH_COMPACT_LEGACY + && last_fde->eh_header_type != EH_COMPACT_HAS_LSDA)) + + { + as_bad (_(".cfi_inline_lsda not valid for this frame")); + ignore_rest_of_line (); + return; + } + +#ifdef md_flush_pending_output + md_flush_pending_output (); +#endif + + align = get_absolute_expression (); + if (align > max_alignment) + { + align = max_alignment; + as_bad (_("Alignment too large: %d. assumed."), align); + } + else if (align < 0) + { + as_warn (_("Alignment negative: 0 assumed.")); + align = 0; + } + + demand_empty_rest_of_line (); + ccseg = CUR_SEG (last_fde); + /* Open .gnu_extab section. */ + cfi_seg = get_cfi_seg (ccseg, ".gnu_extab", + (SEC_ALLOC | SEC_LOAD | SEC_DATA + | DWARF2_EH_FRAME_READ_ONLY), + 1); +#ifdef md_fix_up_eh_frame + md_fix_up_eh_frame (cfi_seg); +#else + (void) cfi_seg; +#endif + + frag_align (align, 0, 0); + record_alignment (now_seg, align); + if (last_fde->eh_header_type == EH_COMPACT_HAS_LSDA) + output_compact_unwind_data (last_fde, align); + + last_fde = NULL; + + return; +} +#else /* !SUPPORT_COMPACT_EH */ +static void +dot_cfi_inline_lsda (int ignored ATTRIBUTE_UNUSED) +{ + as_bad (_(".cfi_inline_lsda is not supported for this target")); + ignore_rest_of_line (); +} +#endif /* Emit a single byte into the current segment. */ @@ -1479,7 +1647,11 @@ output_cie (struct cie_entry *cie, bfd_b offsetT size = encoding_size (cie->per_encoding); out_one (cie->per_encoding); exp = cie->personality; - if ((cie->per_encoding & 0x70) == DW_EH_PE_pcrel) + if (tc_cfi_special_encoding (cie->per_encoding)) + { + tc_cfi_emit_expr (&exp, cie->per_encoding); + } + else if ((cie->per_encoding & 0x70) == DW_EH_PE_pcrel) { #if CFI_DIFF_EXPR_OK exp.X_op = O_subtract; @@ -1516,6 +1688,11 @@ output_cie (struct cie_entry *cie, bfd_b #if CFI_DIFF_EXPR_OK || defined tc_cfi_emit_pcrel_expr enc |= DW_EH_PE_pcrel; #endif +#ifdef DWARF2_FDE_RELOC_ENCODING + /* Allow target to override encoding. */ + enc = DWARF2_FDE_RELOC_ENCODING (enc); +#endif + cie->fde_encoding = enc; if (eh_frame) out_one (enc); @@ -1578,21 +1755,31 @@ output_fde (struct fde_entry *fde, struc if (eh_frame) { - exp.X_op = O_subtract; - exp.X_add_number = 0; + if (tc_cfi_special_encoding (cie->fde_encoding)) + { + exp.X_op = O_symbol; + exp.X_add_symbol = fde->start_address; + tc_cfi_emit_expr (&exp, cie->fde_encoding); + } + else + { + exp.X_op = O_subtract; + exp.X_add_number = 0; #if CFI_DIFF_EXPR_OK - exp.X_add_symbol = fde->start_address; - exp.X_op_symbol = symbol_temp_new_now (); - emit_expr (&exp, DWARF2_FDE_RELOC_SIZE); /* Code offset. */ + exp.X_add_symbol = fde->start_address; + exp.X_op_symbol = symbol_temp_new_now (); + emit_expr (&exp, DWARF2_FDE_RELOC_SIZE); /* Code offset. */ #else - exp.X_op = O_symbol; - exp.X_add_symbol = fde->start_address; -#ifdef tc_cfi_emit_pcrel_expr - tc_cfi_emit_pcrel_expr (&exp, DWARF2_FDE_RELOC_SIZE); /* Code offset. */ + exp.X_op = O_symbol; + exp.X_add_symbol = fde->start_address; + +#if defined(tc_cfi_emit_pcrel_expr) + tc_cfi_emit_pcrel_expr (&exp, DWARF2_FDE_RELOC_SIZE); /* Code offset. */ #else - emit_expr (&exp, DWARF2_FDE_RELOC_SIZE); /* Code offset. */ + emit_expr (&exp, DWARF2_FDE_RELOC_SIZE); /* Code offset. */ #endif #endif + } addr_size = DWARF2_FDE_RELOC_SIZE; } else @@ -1617,7 +1804,11 @@ output_fde (struct fde_entry *fde, struc if (fde->lsda_encoding != DW_EH_PE_omit) { exp = fde->lsda; - if ((fde->lsda_encoding & 0x70) == DW_EH_PE_pcrel) + if (tc_cfi_special_encoding (cie->lsda_encoding)) + { + tc_cfi_emit_expr (&exp, cie->lsda_encoding); + } + else if ((fde->lsda_encoding & 0x70) == DW_EH_PE_pcrel) { #if CFI_DIFF_LSDA_OK exp.X_op = O_subtract; @@ -1821,26 +2012,66 @@ cfi_change_reg_numbers (struct cfi_insn_ #define cfi_change_reg_numbers(insn, cseg) do { } while (0) #endif -static segT -get_cfi_seg (segT cseg, const char *base, flagword flags, int align) +#if SUPPORT_COMPACT_EH +static void +cfi_emit_eh_header (symbolS *sym, bfd_vma addend) { - if (SUPPORT_FRAME_LINKONCE) + expressionS exp; + + exp.X_add_number = addend; + exp.X_add_symbol = sym; + if (tc_cfi_special_encoding (DW_EH_PE_sdata4 | DW_EH_PE_pcrel)) { - struct dwcfi_seg_list *l; + tc_cfi_emit_expr (&exp, DW_EH_PE_sdata4 | DW_EH_PE_pcrel); + } + else + { +#if CFI_DIFF_EXPR_OK + exp.X_op = O_subtract; + exp.X_op_symbol = symbol_temp_new_now (); + emit_expr (&exp, 4); /* Code offset. */ +#elif defined (tc_cfi_emit_pcrel_expr) + exp.X_op = O_symbol; + tc_cfi_emit_pcrel_expr (&exp, 4); /* Code offset. */ +#else + abort(); +#endif + } +} - l = dwcfi_hash_find_or_make (cseg, base, flags); +static void +output_eh_header (struct fde_entry *fde) +{ + char *p; + bfd_vma addend; - cseg = l->seg; - subseg_set (cseg, l->subseg); + if (fde->eh_header_type == EH_COMPACT_INLINE) + addend = 0; + else + addend = 1; + + cfi_emit_eh_header (fde->start_address, addend); + + if (fde->eh_header_type == EH_COMPACT_INLINE) + { + p = frag_more (4); + /* Inline entries always use PR1. */ + *(p++) = 1; + memcpy(p, fde->eh_data, 3); } else { - cseg = subseg_new (base, 0); - bfd_set_section_flags (stdoutput, cseg, flags); + if (fde->eh_header_type == EH_COMPACT_LEGACY) + addend = 1; + else if (fde->eh_header_type == EH_COMPACT_OUTLINE + || fde->eh_header_type == EH_COMPACT_OUTLINE_DONE) + addend = 0; + else + abort (); + cfi_emit_eh_header (fde->eh_loc, addend); } - record_alignment (cseg, align); - return cseg; } +#endif void cfi_finish (void) @@ -1854,13 +2085,13 @@ cfi_finish (void) if (all_fde_data == 0) return; - if ((cfi_sections & CFI_EMIT_eh_frame) != 0) + if ((all_cfi_sections & CFI_EMIT_eh_frame) != 0) { /* Make sure check_eh_frame doesn't do anything with our output. */ save_flag_traditional_format = flag_traditional_format; flag_traditional_format = 1; - if (!SUPPORT_FRAME_LINKONCE) + if (!EH_FRAME_LINKONCE) { /* Open .eh_frame section. */ cfi_seg = get_cfi_seg (NULL, ".eh_frame", @@ -1888,7 +2119,17 @@ cfi_finish (void) for (fde = all_fde_data; fde ; fde = fde->next) { - if (SUPPORT_FRAME_LINKONCE) + if ((fde->sections & CFI_EMIT_eh_frame) == 0) + continue; + +#if SUPPORT_COMPACT_EH + if (fde->eh_header_type == EH_COMPACT_HAS_LSDA) + fde->eh_header_type = EH_COMPACT_LEGACY; + + if (fde->eh_header_type != EH_COMPACT_LEGACY) + continue; +#endif + if (EH_FRAME_LINKONCE) { if (HANDLED (fde)) continue; @@ -1922,20 +2163,111 @@ cfi_finish (void) } cie = select_cie_for_fde (fde, TRUE, &first, 2); + fde->eh_loc = symbol_temp_new_now (); output_fde (fde, cie, TRUE, first, fde->next == NULL ? EH_FRAME_ALIGNMENT : 2); } } - while (SUPPORT_FRAME_LINKONCE && seek_next_seg == 2); + while (EH_FRAME_LINKONCE && seek_next_seg == 2); - if (SUPPORT_FRAME_LINKONCE) + if (EH_FRAME_LINKONCE) for (fde = all_fde_data; fde ; fde = fde->next) SET_HANDLED (fde, 0); +#if SUPPORT_COMPACT_EH + if (compact_eh) + { + /* Create remaining out of line table entries. */ + do + { + ccseg = NULL; + seek_next_seg = 0; + + for (fde = all_fde_data; fde ; fde = fde->next) + { + if ((fde->sections & CFI_EMIT_eh_frame) == 0) + continue; + + if (fde->eh_header_type != EH_COMPACT_OUTLINE) + continue; + if (HANDLED (fde)) + continue; + if (seek_next_seg && CUR_SEG (fde) != ccseg) + { + seek_next_seg = 2; + continue; + } + if (!seek_next_seg) + { + ccseg = CUR_SEG (fde); + /* Open .eh_frame section. */ + cfi_seg = get_cfi_seg (ccseg, ".gnu_extab", + (SEC_ALLOC | SEC_LOAD | SEC_DATA + | DWARF2_EH_FRAME_READ_ONLY), + 1); +#ifdef md_fix_up_eh_frame + md_fix_up_eh_frame (cfi_seg); +#else + (void) cfi_seg; +#endif + seek_next_seg = 1; + } + SET_HANDLED (fde, 1); + + frag_align (1, 0, 0); + record_alignment (now_seg, 1); + output_compact_unwind_data (fde, 1); + } + } + while (EH_FRAME_LINKONCE && seek_next_seg == 2); + + for (fde = all_fde_data; fde ; fde = fde->next) + SET_HANDLED (fde, 0); + + /* Create index table fragments. */ + do + { + ccseg = NULL; + seek_next_seg = 0; + + for (fde = all_fde_data; fde ; fde = fde->next) + { + if ((fde->sections & CFI_EMIT_eh_frame) == 0) + continue; + + if (HANDLED (fde)) + continue; + if (seek_next_seg && CUR_SEG (fde) != ccseg) + { + seek_next_seg = 2; + continue; + } + if (!seek_next_seg) + { + ccseg = CUR_SEG (fde); + /* Open .eh_frame_entry section. */ + cfi_seg = get_cfi_seg (ccseg, ".eh_frame_entry", + (SEC_ALLOC | SEC_LOAD | SEC_DATA + | DWARF2_EH_FRAME_READ_ONLY), + 2); + seek_next_seg = 1; + } + SET_HANDLED (fde, 1); + + output_eh_header (fde); + } + } + while (seek_next_seg == 2); + + for (fde = all_fde_data; fde ; fde = fde->next) + SET_HANDLED (fde, 0); + } +#endif /* SUPPORT_COMPACT_EH */ + flag_traditional_format = save_flag_traditional_format; } - if ((cfi_sections & CFI_EMIT_debug_frame) != 0) + if ((all_cfi_sections & CFI_EMIT_debug_frame) != 0) { int alignment = ffs (DWARF2_ADDR_SIZE (stdoutput)) - 1; @@ -1958,6 +2290,9 @@ cfi_finish (void) for (fde = all_fde_data; fde ; fde = fde->next) { + if ((fde->sections & CFI_EMIT_debug_frame) == 0) + continue; + if (SUPPORT_FRAME_LINKONCE) { if (HANDLED (fde)) @@ -2034,6 +2369,7 @@ const pseudo_typeS cfi_pseudo_table[] = { "cfi_personality", dot_cfi_dummy, 0 }, { "cfi_lsda", dot_cfi_dummy, 0 }, { "cfi_val_encoded_addr", dot_cfi_dummy, 0 }, + { "cfi_inline_lsda", dot_cfi_dummy, 0 }, { NULL, NULL, 0 } }; Index: dw2gencfi.h =================================================================== RCS file: /cvs/src/src/gas/dw2gencfi.h,v retrieving revision 1.10 diff -p -u -r1.10 dw2gencfi.h --- dw2gencfi.h 7 Aug 2011 16:32:20 -0000 1.10 +++ dw2gencfi.h 31 May 2013 17:24:20 -0000 @@ -57,10 +57,18 @@ extern void cfi_add_CFA_restore_state (v #define SUPPORT_FRAME_LINKONCE 0 #endif +#ifdef tc_cfi_fix_eh_ref +#define SUPPORT_COMPACT_EH 1 +#else +#define SUPPORT_COMPACT_EH 0 +#endif + +#define MULTIPLE_FRAME_SECTIONS (SUPPORT_FRAME_LINKONCE || SUPPORT_COMPACT_EH) + struct cfi_insn_data { struct cfi_insn_data *next; -#if SUPPORT_FRAME_LINKONCE +#if MULTIPLE_FRAME_SECTIONS segT cur_seg; #endif int insn; @@ -97,10 +105,19 @@ struct cfi_insn_data } u; }; +enum { + EH_COMPACT_LEGACY, + EH_COMPACT_INLINE, + EH_COMPACT_OUTLINE, + EH_COMPACT_OUTLINE_DONE, + /* Outline if .cfi_inline_lsda used, otherwise legacy FDE. */ + EH_COMPACT_HAS_LSDA +}; + struct fde_entry { struct fde_entry *next; -#if SUPPORT_FRAME_LINKONCE +#if MULTIPLE_FRAME_SECTIONS segT cur_seg; #endif symbolS *start_address; @@ -113,9 +130,16 @@ struct fde_entry expressionS lsda; unsigned int return_column; unsigned int signal_frame; -#if SUPPORT_FRAME_LINKONCE +#if MULTIPLE_FRAME_SECTIONS int handled; #endif + int eh_header_type; + /* Compact unwinding opcodes, not including the PR byte or LSDA. */ + int eh_data_size; + bfd_byte *eh_data; + /* For out of line tables and FDEs. */ + symbolS *eh_loc; + int sections; }; /* The list of all FDEs that have been collected. */