Ejemplo n.º 1
0
static void
dot_cfi_val_encoded_addr (int ignored ATTRIBUTE_UNUSED)
{
  struct cfi_insn_data *insn_ptr;
  offsetT encoding;

  if (frchain_now->frch_cfi_data == NULL)
    {
      as_bad (_("CFI instruction used without previous .cfi_startproc"));
      ignore_rest_of_line ();
      return;
    }

  /* If the last address was not at the current PC, advance to current.  */
  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 ());

  insn_ptr = alloc_cfi_insn_data ();
  insn_ptr->insn = CFI_val_encoded_addr;

  insn_ptr->u.ea.reg = cfi_parse_reg ();

  cfi_parse_separator ();
  encoding = cfi_parse_const ();
  if ((encoding & 0xff) != encoding
      || ((encoding & 0x70) != 0
#if CFI_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"));
      encoding = DW_EH_PE_omit;
    }

  cfi_parse_separator ();
  expression_and_evaluate (&insn_ptr->u.ea.exp);
  switch (insn_ptr->u.ea.exp.X_op)
    {
    case O_symbol:
      break;
    case O_constant:
      if ((encoding & 0x70) != DW_EH_PE_pcrel)
        break;
    default:
      encoding = DW_EH_PE_omit;
      break;
    }

  insn_ptr->u.ea.encoding = encoding;
  if (encoding == DW_EH_PE_omit)
    {
      as_bad (_("wrong third argument to .cfi_val_encoded_addr"));
      ignore_rest_of_line ();
      return;
    }

  demand_empty_rest_of_line ();
}
Ejemplo n.º 2
0
static void
dot_cfi (int arg)
{
    offsetT offset;
    unsigned reg1, reg2;

    if (frchain_now->frch_cfi_data == NULL)
    {
        as_bad (_("CFI instruction used without previous .cfi_startproc"));
        ignore_rest_of_line ();
        return;
    }

    /* If the last address was not at the current PC, advance to current.  */
    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)
    {
    case DW_CFA_offset:
        reg1 = cfi_parse_reg ();
        cfi_parse_separator ();
        offset = cfi_parse_const ();
        cfi_add_CFA_offset (reg1, offset);
        break;

    case CFI_rel_offset:
        reg1 = cfi_parse_reg ();
        cfi_parse_separator ();
        offset = cfi_parse_const ();
        cfi_add_CFA_offset (reg1,
                            offset - frchain_now->frch_cfi_data->cur_cfa_offset);
        break;

    case DW_CFA_def_cfa:
        reg1 = cfi_parse_reg ();
        cfi_parse_separator ();
        offset = cfi_parse_const ();
        cfi_add_CFA_def_cfa (reg1, offset);
        break;

    case DW_CFA_register:
        reg1 = cfi_parse_reg ();
        cfi_parse_separator ();
        reg2 = cfi_parse_reg ();
        cfi_add_CFA_register (reg1, reg2);
        break;

    case DW_CFA_def_cfa_register:
        reg1 = cfi_parse_reg ();
        cfi_add_CFA_def_cfa_register (reg1);
        break;

    case DW_CFA_def_cfa_offset:
        offset = cfi_parse_const ();
        cfi_add_CFA_def_cfa_offset (offset);
        break;

    case CFI_adjust_cfa_offset:
        offset = cfi_parse_const ();
        cfi_add_CFA_def_cfa_offset (frchain_now->frch_cfi_data->cur_cfa_offset
                                    + offset);
        break;

    case DW_CFA_restore:
        for (;;)
        {
            reg1 = cfi_parse_reg ();
            cfi_add_CFA_restore (reg1);
            SKIP_WHITESPACE ();
            if (*input_line_pointer != ',')
                break;
            ++input_line_pointer;
        }
        break;

    case DW_CFA_undefined:
        for (;;)
        {
            reg1 = cfi_parse_reg ();
            cfi_add_CFA_undefined (reg1);
            SKIP_WHITESPACE ();
            if (*input_line_pointer != ',')
                break;
            ++input_line_pointer;
        }
        break;

    case DW_CFA_same_value:
        reg1 = cfi_parse_reg ();
        cfi_add_CFA_same_value (reg1);
        break;

    case CFI_return_column:
        reg1 = cfi_parse_reg ();
        cfi_set_return_column (reg1);
        break;

    case DW_CFA_remember_state:
        cfi_add_CFA_remember_state ();
        break;

    case DW_CFA_restore_state:
        cfi_add_CFA_restore_state ();
        break;

    case DW_CFA_GNU_window_save:
        cfi_add_CFA_insn (DW_CFA_GNU_window_save);
        break;

    case CFI_signal_frame:
        frchain_now->frch_cfi_data->cur_fde_data->signal_frame = 1;
        break;

    default:
        abort ();
    }

    demand_empty_rest_of_line ();
}
Ejemplo n.º 3
0
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 = cfi_parse_const ();
  if (encoding == DW_EH_PE_omit)
    {
      demand_empty_rest_of_line ();
      fde->lsda_encoding = encoding;
      return;
    }

  if ((encoding & 0xff) != encoding
      || ((encoding & 0x70) != 0
#if CFI_DIFF_LSDA_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 ();
}