> Date: Mon, 16 Oct 2017 00:26:10 +0200 (CEST)
> From: Mark Kettenis <[email protected]>
>
> The diff below implements a few more CFI directives in order to be
> able to build clang on sparc64.
>
> ok?
ping?
I'd like to get this in early in the cycle just in case this produces
some fallout in ports...
> Index: gnu/usr.bin/binutils-2.17/gas/dw2gencfi.c
> ===================================================================
> RCS file: /cvs/src/gnu/usr.bin/binutils-2.17/gas/dw2gencfi.c,v
> retrieving revision 1.1.1.1
> diff -u -p -r1.1.1.1 dw2gencfi.c
> --- gnu/usr.bin/binutils-2.17/gas/dw2gencfi.c 24 Apr 2011 20:14:44 -0000
> 1.1.1.1
> +++ gnu/usr.bin/binutils-2.17/gas/dw2gencfi.c 15 Oct 2017 22:22:49 -0000
> @@ -21,6 +21,7 @@
>
> #include "as.h"
> #include "dw2gencfi.h"
> +#include "subsegs.h"
>
>
> /* We re-use DWARF2_LINE_MIN_INSN_LENGTH for the code alignment field
> @@ -87,6 +88,10 @@ struct fde_entry
> symbolS *end_address;
> struct cfi_insn_data *data;
> struct cfi_insn_data **last;
> + unsigned char per_encoding;
> + unsigned char lsda_encoding;
> + expressionS personality;
> + expressionS lsda;
> unsigned int return_column;
> unsigned int signal_frame;
> };
> @@ -97,15 +102,13 @@ struct cie_entry
> symbolS *start_address;
> unsigned int return_column;
> unsigned int signal_frame;
> + unsigned char per_encoding;
> + unsigned char lsda_encoding;
> + expressionS personality;
> struct cfi_insn_data *first, *last;
> };
>
>
> -/* Current open FDE entry. */
> -static struct fde_entry *cur_fde_data;
> -static symbolS *last_address;
> -static offsetT cur_cfa_offset;
> -
> /* List of FDE entries. */
> static struct fde_entry *all_fde_data;
> static struct fde_entry **last_fde_data = &all_fde_data;
> @@ -120,7 +123,14 @@ struct cfa_save_data
> offsetT cfa_offset;
> };
>
> -static struct cfa_save_data *cfa_save_stack;
> +/* Current open FDE entry. */
> +struct frch_cfi_data
> +{
> + struct fde_entry *cur_fde_data;
> + symbolS *last_address;
> + offsetT cur_cfa_offset;
> + struct cfa_save_data *cfa_save_stack;
> +};
>
> /* Construct a new FDE structure and add it to the end of the fde list. */
>
> @@ -129,12 +139,15 @@ alloc_fde_entry (void)
> {
> struct fde_entry *fde = xcalloc (1, sizeof (struct fde_entry));
>
> - cur_fde_data = fde;
> + frchain_now->frch_cfi_data = xcalloc (1, sizeof (struct frch_cfi_data));
> + frchain_now->frch_cfi_data->cur_fde_data = fde;
> *last_fde_data = fde;
> last_fde_data = &fde->next;
>
> fde->last = &fde->data;
> fde->return_column = DWARF2_DEFAULT_RETURN_COLUMN;
> + fde->per_encoding = DW_EH_PE_omit;
> + fde->lsda_encoding = DW_EH_PE_omit;
>
> return fde;
> }
> @@ -149,6 +162,7 @@ static struct cfi_insn_data *
> alloc_cfi_insn_data (void)
> {
> struct cfi_insn_data *insn = xcalloc (1, sizeof (struct cfi_insn_data));
> + struct fde_entry *cur_fde_data = frchain_now->frch_cfi_data->cur_fde_data;
>
> *cur_fde_data->last = insn;
> cur_fde_data->last = &insn->next;
> @@ -163,7 +177,7 @@ cfi_new_fde (symbolS *label)
> {
> struct fde_entry *fde = alloc_fde_entry ();
> fde->start_address = label;
> - last_address = label;
> + frchain_now->frch_cfi_data->last_address = label;
> }
>
> /* End the currently open FDE. */
> @@ -171,8 +185,9 @@ cfi_new_fde (symbolS *label)
> void
> cfi_end_fde (symbolS *label)
> {
> - cur_fde_data->end_address = label;
> - cur_fde_data = NULL;
> + frchain_now->frch_cfi_data->cur_fde_data->end_address = label;
> + free (frchain_now->frch_cfi_data);
> + frchain_now->frch_cfi_data = NULL;
> }
>
> /* Set the return column for the current FDE. */
> @@ -180,7 +195,7 @@ cfi_end_fde (symbolS *label)
> void
> cfi_set_return_column (unsigned regno)
> {
> - cur_fde_data->return_column = regno;
> + frchain_now->frch_cfi_data->cur_fde_data->return_column = regno;
> }
>
> /* Universal functions to store new instructions. */
> @@ -239,10 +254,10 @@ cfi_add_advance_loc (symbolS *label)
> struct cfi_insn_data *insn = alloc_cfi_insn_data ();
>
> insn->insn = DW_CFA_advance_loc;
> - insn->u.ll.lab1 = last_address;
> + insn->u.ll.lab1 = frchain_now->frch_cfi_data->last_address;
> insn->u.ll.lab2 = label;
>
> - last_address = label;
> + frchain_now->frch_cfi_data->last_address = label;
> }
>
> /* Add a DW_CFA_offset record to the CFI data. */
> @@ -252,6 +267,7 @@ cfi_add_CFA_offset (unsigned regno, offs
> {
> unsigned int abs_data_align;
>
> + assert (DWARF2_CIE_DATA_ALIGNMENT != 0);
> cfi_add_CFA_insn_reg_offset (DW_CFA_offset, regno, offset);
>
> abs_data_align = (DWARF2_CIE_DATA_ALIGNMENT < 0
> @@ -266,7 +282,7 @@ void
> cfi_add_CFA_def_cfa (unsigned regno, offsetT offset)
> {
> cfi_add_CFA_insn_reg_offset (DW_CFA_def_cfa, regno, offset);
> - cur_cfa_offset = offset;
> + frchain_now->frch_cfi_data->cur_cfa_offset = offset;
> }
>
> /* Add a DW_CFA_register record to the CFI data. */
> @@ -291,7 +307,7 @@ void
> cfi_add_CFA_def_cfa_offset (offsetT offset)
> {
> cfi_add_CFA_insn_offset (DW_CFA_def_cfa_offset, offset);
> - cur_cfa_offset = offset;
> + frchain_now->frch_cfi_data->cur_cfa_offset = offset;
> }
>
> void
> @@ -320,9 +336,9 @@ cfi_add_CFA_remember_state (void)
> cfi_add_CFA_insn (DW_CFA_remember_state);
>
> p = xmalloc (sizeof (*p));
> - p->cfa_offset = cur_cfa_offset;
> - p->next = cfa_save_stack;
> - cfa_save_stack = p;
> + p->cfa_offset = frchain_now->frch_cfi_data->cur_cfa_offset;
> + p->next = frchain_now->frch_cfi_data->cfa_save_stack;
> + frchain_now->frch_cfi_data->cfa_save_stack = p;
> }
>
> void
> @@ -332,11 +348,11 @@ cfi_add_CFA_restore_state (void)
>
> cfi_add_CFA_insn (DW_CFA_restore_state);
>
> - p = cfa_save_stack;
> + p = frchain_now->frch_cfi_data->cfa_save_stack;
> if (p)
> {
> - cur_cfa_offset = p->cfa_offset;
> - cfa_save_stack = p->next;
> + frchain_now->frch_cfi_data->cur_cfa_offset = p->cfa_offset;
> + frchain_now->frch_cfi_data->cfa_save_stack = p->next;
> free (p);
> }
> else
> @@ -350,6 +366,9 @@ static void dot_cfi (int);
> static void dot_cfi_escape (int);
> static void dot_cfi_startproc (int);
> static void dot_cfi_endproc (int);
> +static void dot_cfi_personality (int);
> +static void dot_cfi_lsda (int);
> +static void dot_cfi_sections (int);
>
> /* Fake CFI type; outside the byte range of any real CFI insn. */
> #define CFI_adjust_cfa_offset 0x100
> @@ -378,6 +397,9 @@ const pseudo_typeS cfi_pseudo_table[] =
> { "cfi_window_save", dot_cfi, DW_CFA_GNU_window_save },
> { "cfi_escape", dot_cfi_escape, 0 },
> { "cfi_signal_frame", dot_cfi, CFI_signal_frame },
> + { "cfi_personality", dot_cfi_personality, 0 },
> + { "cfi_lsda", dot_cfi_lsda, 0 },
> + { "cfi_sections", dot_cfi_sections, 0 },
> { NULL, NULL, 0 }
> };
>
> @@ -448,7 +470,7 @@ dot_cfi (int arg)
> offsetT offset;
> unsigned reg1, reg2;
>
> - if (!cur_fde_data)
> + if (frchain_now->frch_cfi_data == NULL)
> {
> as_bad (_("CFI instruction used without previous .cfi_startproc"));
> ignore_rest_of_line ();
> @@ -456,8 +478,9 @@ dot_cfi (int arg)
> }
>
> /* If the last address was not at the current PC, advance to current. */
> - if (symbol_get_frag (last_address) != frag_now
> - || S_GET_VALUE (last_address) != frag_now_fix ())
> + if (symbol_get_frag (frchain_now->frch_cfi_data->last_address) != frag_now
> + || S_GET_VALUE (frchain_now->frch_cfi_data->last_address)
> + != frag_now_fix ())
> cfi_add_advance_loc (symbol_temp_new_now ());
>
> switch (arg)
> @@ -473,7 +496,8 @@ dot_cfi (int arg)
> reg1 = cfi_parse_reg ();
> cfi_parse_separator ();
> offset = cfi_parse_const ();
> - cfi_add_CFA_offset (reg1, offset - cur_cfa_offset);
> + cfi_add_CFA_offset (reg1,
> + offset - frchain_now->frch_cfi_data->cur_cfa_offset);
> break;
>
> case DW_CFA_def_cfa:
> @@ -502,7 +526,8 @@ dot_cfi (int arg)
>
> case CFI_adjust_cfa_offset:
> offset = cfi_parse_const ();
> - cfi_add_CFA_def_cfa_offset (cur_cfa_offset + offset);
> + cfi_add_CFA_def_cfa_offset (frchain_now->frch_cfi_data->cur_cfa_offset
> + + offset);
> break;
>
> case DW_CFA_restore:
> @@ -552,7 +577,7 @@ dot_cfi (int arg)
> break;
>
> case CFI_signal_frame:
> - cur_fde_data->signal_frame = 1;
> + frchain_now->frch_cfi_data->cur_fde_data->signal_frame = 1;
> break;
>
> default:
> @@ -568,7 +593,7 @@ dot_cfi_escape (int ignored ATTRIBUTE_UN
> struct cfi_escape_data *head, **tail, *e;
> struct cfi_insn_data *insn;
>
> - if (!cur_fde_data)
> + if (frchain_now->frch_cfi_data == NULL)
> {
> as_bad (_("CFI instruction used without previous .cfi_startproc"));
> ignore_rest_of_line ();
> @@ -576,8 +601,9 @@ dot_cfi_escape (int ignored ATTRIBUTE_UN
> }
>
> /* If the last address was not at the current PC, advance to current. */
> - if (symbol_get_frag (last_address) != frag_now
> - || S_GET_VALUE (last_address) != frag_now_fix ())
> + if (symbol_get_frag (frchain_now->frch_cfi_data->last_address) != frag_now
> + || S_GET_VALUE (frchain_now->frch_cfi_data->last_address)
> + != frag_now_fix ())
> cfi_add_advance_loc (symbol_temp_new_now ());
>
> tail = &head;
> @@ -600,11 +626,153 @@ dot_cfi_escape (int ignored ATTRIBUTE_UN
> }
>
> static void
> +dot_cfi_personality (int ignored ATTRIBUTE_UNUSED)
> +{
> + struct fde_entry *fde;
> + offsetT encoding;
> +
> + if (frchain_now->frch_cfi_data == NULL)
> + {
> + as_bad (_("CFI instruction used without previous .cfi_startproc"));
> + ignore_rest_of_line ();
> + return;
> + }
> +
> + fde = frchain_now->frch_cfi_data->cur_fde_data;
> + encoding = get_absolute_expression ();
> + if (encoding == DW_EH_PE_omit)
> + {
> + demand_empty_rest_of_line ();
> + fde->per_encoding = encoding;
> + return;
> + }
> +
> + if ((encoding & 0xff) != encoding
> + || ((encoding & 0x70) != 0
> +#if defined DIFF_EXPR_OK || defined tc_cfi_emit_pcrel_expr
> + && (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)
> + {
> + as_bad (_("invalid or unsupported encoding in .cfi_personality"));
> + ignore_rest_of_line ();
> + return;
> + }
> +
> + if (*input_line_pointer++ != ',')
> + {
> + as_bad (_(".cfi_personality requires encoding and symbol arguments"));
> + ignore_rest_of_line ();
> + return;
> + }
> +
> + expression_and_evaluate (&fde->personality);
> + switch (fde->personality.X_op)
> + {
> + case O_symbol:
> + break;
> + case O_constant:
> + if ((encoding & 0x70) == DW_EH_PE_pcrel)
> + encoding = DW_EH_PE_omit;
> + break;
> + default:
> + encoding = DW_EH_PE_omit;
> + break;
> + }
> +
> + fde->per_encoding = encoding;
> +
> + if (encoding == DW_EH_PE_omit)
> + {
> + as_bad (_("wrong second argument to .cfi_personality"));
> + ignore_rest_of_line ();
> + return;
> + }
> +
> + demand_empty_rest_of_line ();
> +}
> +
> +static void
> +dot_cfi_lsda (int ignored ATTRIBUTE_UNUSED)
> +{
> + struct fde_entry *fde;
> + offsetT encoding;
> +
> + if (frchain_now->frch_cfi_data == NULL)
> + {
> + as_bad (_("CFI instruction used without previous .cfi_startproc"));
> + ignore_rest_of_line ();
> + return;
> + }
> +
> + fde = frchain_now->frch_cfi_data->cur_fde_data;
> + encoding = get_absolute_expression ();
> + if (encoding == DW_EH_PE_omit)
> + {
> + demand_empty_rest_of_line ();
> + fde->lsda_encoding = encoding;
> + return;
> + }
> +
> + if ((encoding & 0xff) != encoding
> + || ((encoding & 0x70) != 0
> +#if defined DIFF_EXPR_OK || defined tc_cfi_emit_pcrel_expr
> + && (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)
> + {
> + as_bad (_("invalid or unsupported encoding in .cfi_lsda"));
> + ignore_rest_of_line ();
> + return;
> + }
> +
> + if (*input_line_pointer++ != ',')
> + {
> + as_bad (_(".cfi_lsda requires encoding and symbol arguments"));
> + ignore_rest_of_line ();
> + return;
> + }
> +
> + fde->lsda_encoding = encoding;
> +
> + expression_and_evaluate (&fde->lsda);
> + switch (fde->lsda.X_op)
> + {
> + case O_symbol:
> + break;
> + case O_constant:
> + if ((encoding & 0x70) == DW_EH_PE_pcrel)
> + encoding = DW_EH_PE_omit;
> + break;
> + default:
> + encoding = DW_EH_PE_omit;
> + break;
> + }
> +
> + fde->lsda_encoding = encoding;
> +
> + if (encoding == DW_EH_PE_omit)
> + {
> + as_bad (_("wrong second argument to .cfi_lsda"));
> + ignore_rest_of_line ();
> + return;
> + }
> +
> + demand_empty_rest_of_line ();
> +}
> +
> +static void
> dot_cfi_startproc (int ignored ATTRIBUTE_UNUSED)
> {
> int simple = 0;
>
> - if (cur_fde_data)
> + if (frchain_now->frch_cfi_data != NULL)
> {
> as_bad (_("previous CFI entry not closed (missing .cfi_endproc)"));
> ignore_rest_of_line ();
> @@ -631,7 +799,7 @@ dot_cfi_startproc (int ignored ATTRIBUTE
> }
> demand_empty_rest_of_line ();
>
> - cur_cfa_offset = 0;
> + frchain_now->frch_cfi_data->cur_cfa_offset = 0;
> if (!simple)
> tc_cfi_frame_initial_instructions ();
> }
> @@ -639,7 +807,7 @@ dot_cfi_startproc (int ignored ATTRIBUTE
> static void
> dot_cfi_endproc (int ignored ATTRIBUTE_UNUSED)
> {
> - if (! cur_fde_data)
> + if (frchain_now->frch_cfi_data == NULL)
> {
> as_bad (_(".cfi_endproc without corresponding .cfi_startproc"));
> ignore_rest_of_line ();
> @@ -651,6 +819,12 @@ dot_cfi_endproc (int ignored ATTRIBUTE_U
> demand_empty_rest_of_line ();
> }
>
> +static void
> +dot_cfi_sections (int ignored ATTRIBUTE_UNUSED)
> +{
> + ignore_rest_of_line ();
> +}
> +
>
> /* Emit a single byte into the current segment. */
>
> @@ -714,18 +888,18 @@ output_cfi_insn (struct cfi_insn_data *i
> out_one (DW_CFA_advance_loc + scaled);
> else if (delta <= 0xFF)
> {
> - out_one (DW_CFA_advance_loc1);
> - out_one (delta);
> + out_one (DW_CFA_advance_loc1);
> + out_one (delta);
> }
> else if (delta <= 0xFFFF)
> {
> - out_one (DW_CFA_advance_loc2);
> - out_two (delta);
> + out_one (DW_CFA_advance_loc2);
> + out_two (delta);
> }
> else
> {
> - out_one (DW_CFA_advance_loc4);
> - out_four (delta);
> + out_one (DW_CFA_advance_loc4);
> + out_four (delta);
> }
> }
> else
> @@ -850,12 +1024,33 @@ output_cfi_insn (struct cfi_insn_data *i
> }
> }
>
> +static offsetT
> +encoding_size (unsigned char encoding)
> +{
> + if (encoding == DW_EH_PE_omit)
> + return 0;
> + switch (encoding & 0x7)
> + {
> + case 0:
> + return bfd_get_arch_size (stdoutput) == 64 ? 8 : 4;
> + case DW_EH_PE_udata2:
> + return 2;
> + case DW_EH_PE_udata4:
> + return 4;
> + case DW_EH_PE_udata8:
> + return 8;
> + default:
> + abort ();
> + }
> +}
> +
> static void
> output_cie (struct cie_entry *cie)
> {
> symbolS *after_size_address, *end_address;
> expressionS exp;
> struct cfi_insn_data *i;
> + offsetT augmentation_size;
>
> cie->start_address = symbol_temp_new_now ();
> after_size_address = symbol_temp_make ();
> @@ -871,6 +1066,10 @@ output_cie (struct cie_entry *cie)
> out_four (0); /* CIE id. */
> out_one (DW_CIE_VERSION); /* Version. */
> out_one ('z'); /* Augmentation. */
> + if (cie->per_encoding != DW_EH_PE_omit)
> + out_one ('P');
> + if (cie->lsda_encoding != DW_EH_PE_omit)
> + out_one ('L');
> out_one ('R');
> if (cie->signal_frame)
> out_one ('S');
> @@ -881,7 +1080,32 @@ output_cie (struct cie_entry *cie)
> out_one (cie->return_column);
> else
> out_uleb128 (cie->return_column);
> - out_uleb128 (1); /* Augmentation size. */
> + augmentation_size = 1 + (cie->lsda_encoding != DW_EH_PE_omit);
> + if (cie->per_encoding != DW_EH_PE_omit)
> + augmentation_size += 1 + encoding_size (cie->per_encoding);
> + out_uleb128 (augmentation_size); /* Augmentation size. */
> + if (cie->per_encoding != DW_EH_PE_omit)
> + {
> + offsetT size = encoding_size (cie->per_encoding);
> + out_one (cie->per_encoding);
> + exp = cie->personality;
> + if ((cie->per_encoding & 0x70) == DW_EH_PE_pcrel)
> + {
> +#ifdef DIFF_EXPR_OK
> + exp.X_op = O_subtract;
> + exp.X_op_symbol = symbol_temp_new_now ();
> + emit_expr (&exp, size);
> +#elif defined (tc_cfi_emit_pcrel_expr)
> + tc_cfi_emit_pcrel_expr (&exp, size);
> +#else
> + abort ();
> +#endif
> + }
> + else
> + emit_expr (&exp, size);
> + }
> + if (cie->lsda_encoding != DW_EH_PE_omit)
> + out_one (cie->lsda_encoding);
> #if defined DIFF_EXPR_OK || defined tc_cfi_emit_pcrel_expr
> out_one (DW_EH_PE_pcrel | DW_EH_PE_sdata4);
> #else
> @@ -902,6 +1126,7 @@ output_fde (struct fde_entry *fde, struc
> {
> symbolS *after_size_address, *end_address;
> expressionS exp;
> + offsetT augmentation_size;
>
> after_size_address = symbol_temp_make ();
> end_address = symbol_temp_make ();
> @@ -917,7 +1142,7 @@ output_fde (struct fde_entry *fde, struc
> exp.X_op_symbol = cie->start_address;
> emit_expr (&exp, 4); /* CIE offset. */
>
> -#ifdef DIFF_EXPR_OK
> +#ifdef DIFF_EXPR_OK
> exp.X_add_symbol = fde->start_address;
> exp.X_op_symbol = symbol_temp_new_now ();
> emit_expr (&exp, 4); /* Code offset. */
> @@ -937,7 +1162,27 @@ output_fde (struct fde_entry *fde, struc
> exp.X_op_symbol = fde->start_address; /* Code length. */
> emit_expr (&exp, 4);
>
> - out_uleb128 (0); /* Augmentation size. */
> + augmentation_size = encoding_size (fde->lsda_encoding);
> + out_uleb128 (augmentation_size); /* Augmentation size. */
> +
> + if (fde->lsda_encoding != DW_EH_PE_omit)
> + {
> + exp = fde->lsda;
> + if ((fde->lsda_encoding & 0x70) == DW_EH_PE_pcrel)
> + {
> +#ifdef DIFF_EXPR_OK
> + exp.X_op = O_subtract;
> + exp.X_op_symbol = symbol_temp_new_now ();
> + emit_expr (&exp, augmentation_size);
> +#elif defined (tc_cfi_emit_pcrel_expr)
> + tc_cfi_emit_pcrel_expr (&exp, augmentation_size);
> +#else
> + abort ();
> +#endif
> + }
> + else
> + emit_expr (&exp, augmentation_size);
> + }
>
> for (; first; first = first->next)
> output_cfi_insn (first);
> @@ -955,8 +1200,31 @@ select_cie_for_fde (struct fde_entry *fd
> for (cie = cie_root; cie; cie = cie->next)
> {
> if (cie->return_column != fde->return_column
> - || cie->signal_frame != fde->signal_frame)
> + || cie->signal_frame != fde->signal_frame
> + || cie->per_encoding != fde->per_encoding
> + || cie->lsda_encoding != fde->lsda_encoding)
> continue;
> + if (cie->per_encoding != DW_EH_PE_omit)
> + {
> + if (cie->personality.X_op != fde->personality.X_op
> + || cie->personality.X_add_number
> + != fde->personality.X_add_number)
> + continue;
> + switch (cie->personality.X_op)
> + {
> + case O_constant:
> + if (cie->personality.X_unsigned != fde->personality.X_unsigned)
> + continue;
> + break;
> + case O_symbol:
> + if (cie->personality.X_add_symbol
> + != fde->personality.X_add_symbol)
> + continue;
> + break;
> + default:
> + abort ();
> + }
> + }
> for (i = cie->first, j = fde->data;
> i != cie->last && j != NULL;
> i = i->next, j = j->next)
> @@ -1029,6 +1297,9 @@ select_cie_for_fde (struct fde_entry *fd
> cie_root = cie;
> cie->return_column = fde->return_column;
> cie->signal_frame = fde->signal_frame;
> + cie->per_encoding = fde->per_encoding;
> + cie->lsda_encoding = fde->lsda_encoding;
> + cie->personality = fde->personality;
> cie->first = fde->data;
>
> for (i = cie->first; i ; i = i->next)
> @@ -1052,12 +1323,6 @@ cfi_finish (void)
> struct fde_entry *fde;
> int save_flag_traditional_format;
>
> - if (cur_fde_data)
> - {
> - as_bad (_("open CFI at the end of file; missing .cfi_endproc
> directive"));
> - cur_fde_data->end_address = cur_fde_data->start_address;
> - }
> -
> if (all_fde_data == 0)
> return;
>
> @@ -1076,6 +1341,12 @@ cfi_finish (void)
> {
> struct cfi_insn_data *first;
> struct cie_entry *cie;
> +
> + if (fde->end_address == NULL)
> + {
> + as_bad (_("open CFI at the end of file; missing .cfi_endproc
> directive"));
> + fde->end_address = fde->start_address;
> + }
>
> cie = select_cie_for_fde (fde, &first);
> output_fde (fde, cie, first, fde->next == NULL ? EH_FRAME_ALIGNMENT :
> 2);
> Index: gnu/usr.bin/binutils-2.17/gas/subsegs.c
> ===================================================================
> RCS file: /cvs/src/gnu/usr.bin/binutils-2.17/gas/subsegs.c,v
> retrieving revision 1.1.1.1
> diff -u -p -r1.1.1.1 subsegs.c
> --- gnu/usr.bin/binutils-2.17/gas/subsegs.c 24 Apr 2011 20:14:44 -0000
> 1.1.1.1
> +++ gnu/usr.bin/binutils-2.17/gas/subsegs.c 15 Oct 2017 22:22:49 -0000
> @@ -187,6 +187,7 @@ subseg_set_rest (segT seg, subsegT subse
> #endif
> newP->frch_frag_now = frag_alloc (&newP->frch_obstack);
> newP->frch_frag_now->fr_type = rs_fill;
> + newP->frch_cfi_data = NULL;
>
> newP->frch_root = newP->frch_last = newP->frch_frag_now;
>
> Index: gnu/usr.bin/binutils-2.17/gas/subsegs.h
> ===================================================================
> RCS file: /cvs/src/gnu/usr.bin/binutils-2.17/gas/subsegs.h,v
> retrieving revision 1.1.1.1
> diff -u -p -r1.1.1.1 subsegs.h
> --- gnu/usr.bin/binutils-2.17/gas/subsegs.h 24 Apr 2011 20:14:44 -0000
> 1.1.1.1
> +++ gnu/usr.bin/binutils-2.17/gas/subsegs.h 15 Oct 2017 22:22:49 -0000
> @@ -40,6 +40,8 @@
>
> #include "obstack.h"
>
> +struct frch_cfi_data;
> +
> struct frchain /* control building of a frag chain */
> { /* FRCH = FRagment CHain control */
> struct frag *frch_root; /* 1st struct frag in chain, or NULL */
> @@ -51,6 +53,7 @@ struct frchain /* control building of
> fixS *fix_tail; /* Last fixup for this subsegment. */
> struct obstack frch_obstack; /* for objects in this frag chain */
> fragS *frch_frag_now; /* frag_now for this subsegment */
> + struct frch_cfi_data *frch_cfi_data;
> };
>
> typedef struct frchain frchainS;
>
>