static void
cfi_add_CFA_insn(int insn)
{
    struct cfi_insn_data *insn_ptr = alloc_cfi_insn_data ();

    insn_ptr->insn = insn;
}
static void
cfi_add_CFA_insn_offset (int insn, offsetT offset)
{
    struct cfi_insn_data *insn_ptr = alloc_cfi_insn_data ();

    insn_ptr->insn = insn;
    insn_ptr->u.i = offset;
}
static void
cfi_add_CFA_insn_reg (int insn, unsigned regno)
{
    struct cfi_insn_data *insn_ptr = alloc_cfi_insn_data ();

    insn_ptr->insn = insn;
    insn_ptr->u.r = regno;
}
static void
cfi_add_CFA_insn_reg_offset (int insn, unsigned regno, offsetT offset)
{
    struct cfi_insn_data *insn_ptr = alloc_cfi_insn_data ();

    insn_ptr->insn = insn;
    insn_ptr->u.ri.reg = regno;
    insn_ptr->u.ri.offset = offset;
}
static void
cfi_add_CFA_insn_reg_reg (int insn, unsigned reg1, unsigned reg2)
{
    struct cfi_insn_data *insn_ptr = alloc_cfi_insn_data ();

    insn_ptr->insn = insn;
    insn_ptr->u.rr.reg1 = reg1;
    insn_ptr->u.rr.reg2 = reg2;
}
void
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 = frchain_now->frch_cfi_data->last_address;
    insn->u.ll.lab2 = label;

    frchain_now->frch_cfi_data->last_address = label;
}
static void
dot_cfi_escape (int ignored ATTRIBUTE_UNUSED)
{
    struct cfi_escape_data *head, **tail, *e;
    struct cfi_insn_data *insn;

    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 ());

    tail = &head;
    do
    {
        e = xmalloc (sizeof (*e));
        do_parse_cons_expression (&e->exp, 1);
        *tail = e;
        tail = &e->next;
    }
    while (*input_line_pointer++ == ',');
    *tail = NULL;

    insn = alloc_cfi_insn_data ();
    insn->insn = CFI_escape;
    insn->u.esc = head;

    --input_line_pointer;
    demand_empty_rest_of_line ();
}
Exemple #8
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 ();
}