> Date: Mon, 16 Oct 2017 00:26:10 +0200 (CEST)
> From: Mark Kettenis <mark.kette...@xs4all.nl>
> 
> 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;
> 
> 

Reply via email to