Back to index

cell-binutils  2.17cvs20070401
Classes | Defines | Functions | Variables
dw2gencfi.c File Reference
#include "as.h"
#include "dw2gencfi.h"
#include "subsegs.h"

Go to the source code of this file.

Classes

struct  cfi_insn_data
struct  fde_entry
struct  cie_entry
struct  cfa_save_data
struct  frch_cfi_data
union  cfi_insn_data.u
struct  cfi_insn_data.u.ri
struct  cfi_insn_data.u.rr
struct  cfi_insn_data.u.ll
struct  cfi_escape_data.u.esc

Defines

#define DWARF2_LINE_MIN_INSN_LENGTH   1
#define DWARF2_DEFAULT_RETURN_COLUMN   0
#define DWARF2_CIE_DATA_ALIGNMENT   1
#define EH_FRAME_ALIGNMENT   (bfd_get_arch_size (stdoutput) == 64 ? 3 : 2)
#define tc_cfi_frame_initial_instructions()   ((void)0)
#define CFI_adjust_cfa_offset   0x100
#define CFI_return_column   0x101
#define CFI_rel_offset   0x102
#define CFI_escape   0x103
#define CFI_signal_frame   0x104

Functions

static struct fde_entryalloc_fde_entry (void)
static struct cfi_insn_dataalloc_cfi_insn_data (void)
void cfi_new_fde (symbolS *label)
void cfi_end_fde (symbolS *label)
void cfi_set_return_column (unsigned regno)
static void cfi_add_CFA_insn (int insn)
static void cfi_add_CFA_insn_reg (int insn, unsigned regno)
static void cfi_add_CFA_insn_offset (int insn, offsetT offset)
static void cfi_add_CFA_insn_reg_reg (int insn, unsigned reg1, unsigned reg2)
static void cfi_add_CFA_insn_reg_offset (int insn, unsigned regno, offsetT offset)
void cfi_add_advance_loc (symbolS *label)
void cfi_add_CFA_offset (unsigned regno, offsetT offset)
void cfi_add_CFA_def_cfa (unsigned regno, offsetT offset)
void cfi_add_CFA_register (unsigned reg1, unsigned reg2)
void cfi_add_CFA_def_cfa_register (unsigned regno)
void cfi_add_CFA_def_cfa_offset (offsetT offset)
void cfi_add_CFA_restore (unsigned regno)
void cfi_add_CFA_undefined (unsigned regno)
void cfi_add_CFA_same_value (unsigned regno)
void cfi_add_CFA_remember_state (void)
void cfi_add_CFA_restore_state (void)
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 cfi_parse_separator (void)
static unsigned cfi_parse_reg (void)
static offsetT cfi_parse_const (void)
static void dot_cfi_escape (int ignored ATTRIBUTE_UNUSED)
static void dot_cfi_personality (int ignored ATTRIBUTE_UNUSED)
static void dot_cfi_lsda (int ignored ATTRIBUTE_UNUSED)
static void dot_cfi_startproc (int ignored ATTRIBUTE_UNUSED)
static void dot_cfi_endproc (int ignored ATTRIBUTE_UNUSED)
static void out_one (int byte)
static void out_two (int data)
static void out_four (int data)
static void out_uleb128 (addressT value)
static void out_sleb128 (offsetT value)
static void output_cfi_insn (struct cfi_insn_data *insn)
static offsetT encoding_size (unsigned char encoding)
static void output_cie (struct cie_entry *cie)
static void output_fde (struct fde_entry *fde, struct cie_entry *cie, struct cfi_insn_data *first, int align)
static struct cie_entryselect_cie_for_fde (struct fde_entry *fde, struct cfi_insn_data **pfirst)
void cfi_finish (void)

Variables

static struct fde_entryall_fde_data
static struct fde_entry ** last_fde_data = &all_fde_data
static struct cie_entrycie_root
const pseudo_typeS cfi_pseudo_table []

Class Documentation

struct cfi_insn_data

Definition at line 54 of file dw2gencfi.c.

Collaboration diagram for cfi_insn_data:
Class Members
int insn
struct cfi_insn_data * next
union cfi_insn_data u
struct fde_entry

Definition at line 84 of file dw2gencfi.c.

Collaboration diagram for fde_entry:
Class Members
struct cfi_insn_data * data
symbolS * end_address
struct cfi_insn_data ** last
expressionS lsda
unsigned char lsda_encoding
struct fde_entry * next
unsigned char per_encoding
expressionS personality
unsigned int return_column
unsigned int signal_frame
symbolS * start_address
struct cie_entry

Definition at line 99 of file dw2gencfi.c.

Collaboration diagram for cie_entry:
Class Members
struct cfi_insn_data * first
struct cfi_insn_data * last
unsigned char lsda_encoding
struct cie_entry * next
unsigned char per_encoding
expressionS personality
unsigned int return_column
unsigned int signal_frame
symbolS * start_address
struct cfa_save_data

Definition at line 120 of file dw2gencfi.c.

Collaboration diagram for cfa_save_data:
Class Members
offsetT cfa_offset
struct cfa_save_data * next
struct frch_cfi_data

Definition at line 127 of file dw2gencfi.c.

Collaboration diagram for frch_cfi_data:
Class Members
struct cfa_save_data * cfa_save_stack
offsetT cur_cfa_offset
struct fde_entry * cur_fde_data
symbolS * last_address
union cfi_insn_data.u

Definition at line 58 of file dw2gencfi.c.

Class Members
u esc
offsetT i
u ll
unsigned r
u ri
u rr
struct cfi_insn_data.u.ri

Definition at line 59 of file dw2gencfi.c.

Class Members
offsetT offset
unsigned reg
struct cfi_insn_data.u.rr

Definition at line 64 of file dw2gencfi.c.

Class Members
unsigned reg1
unsigned reg2
struct cfi_insn_data.u.ll

Definition at line 72 of file dw2gencfi.c.

Class Members
symbolS * lab1
symbolS * lab2
struct cfi_insn_data::cfi_escape_data.u.esc

Definition at line 77 of file dw2gencfi.c.

Class Members
expressionS exp
struct cfi_escape_data * next

Define Documentation

#define CFI_adjust_cfa_offset   0x100

Definition at line 373 of file dw2gencfi.c.

#define CFI_escape   0x103

Definition at line 376 of file dw2gencfi.c.

#define CFI_rel_offset   0x102

Definition at line 375 of file dw2gencfi.c.

#define CFI_return_column   0x101

Definition at line 374 of file dw2gencfi.c.

#define CFI_signal_frame   0x104

Definition at line 377 of file dw2gencfi.c.

#define DWARF2_CIE_DATA_ALIGNMENT   1

Definition at line 41 of file dw2gencfi.c.

Definition at line 38 of file dw2gencfi.c.

Definition at line 30 of file dw2gencfi.c.

#define EH_FRAME_ALIGNMENT   (bfd_get_arch_size (stdoutput) == 64 ? 3 : 2)

Definition at line 46 of file dw2gencfi.c.

#define tc_cfi_frame_initial_instructions ( )    ((void)0)

Definition at line 50 of file dw2gencfi.c.


Function Documentation

static struct cfi_insn_data* alloc_cfi_insn_data ( void  ) [static, read]

Definition at line 162 of file dw2gencfi.c.

{
  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;

  return insn;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static struct fde_entry* alloc_fde_entry ( void  ) [static, read]

Definition at line 138 of file dw2gencfi.c.

{
  struct fde_entry *fde = xcalloc (1, sizeof (struct fde_entry));

  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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void cfi_add_advance_loc ( symbolS *  label)

Definition at line 252 of file dw2gencfi.c.

{
  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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void cfi_add_CFA_def_cfa ( unsigned  regno,
offsetT  offset 
)

Definition at line 282 of file dw2gencfi.c.

{
  cfi_add_CFA_insn_reg_offset (DW_CFA_def_cfa, regno, offset);
  frchain_now->frch_cfi_data->cur_cfa_offset = offset;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 307 of file dw2gencfi.c.

{
  cfi_add_CFA_insn_offset (DW_CFA_def_cfa_offset, offset);
  frchain_now->frch_cfi_data->cur_cfa_offset = offset;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 299 of file dw2gencfi.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static void cfi_add_CFA_insn ( int  insn) [static]

Definition at line 204 of file dw2gencfi.c.

{
  struct cfi_insn_data *insn_ptr = alloc_cfi_insn_data ();

  insn_ptr->insn = insn;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void cfi_add_CFA_insn_offset ( int  insn,
offsetT  offset 
) [static]

Definition at line 221 of file dw2gencfi.c.

{
  struct cfi_insn_data *insn_ptr = alloc_cfi_insn_data ();

  insn_ptr->insn = insn;
  insn_ptr->u.i = offset;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void cfi_add_CFA_insn_reg ( int  insn,
unsigned  regno 
) [static]

Definition at line 212 of file dw2gencfi.c.

{
  struct cfi_insn_data *insn_ptr = alloc_cfi_insn_data ();

  insn_ptr->insn = insn;
  insn_ptr->u.r = regno;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void cfi_add_CFA_insn_reg_offset ( int  insn,
unsigned  regno,
offsetT  offset 
) [static]

Definition at line 240 of file dw2gencfi.c.

{
  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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void cfi_add_CFA_insn_reg_reg ( int  insn,
unsigned  reg1,
unsigned  reg2 
) [static]

Definition at line 230 of file dw2gencfi.c.

{
  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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void cfi_add_CFA_offset ( unsigned  regno,
offsetT  offset 
)

Definition at line 266 of file dw2gencfi.c.

{
  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
                  ? -DWARF2_CIE_DATA_ALIGNMENT : DWARF2_CIE_DATA_ALIGNMENT);
  if (offset % abs_data_align)
    as_bad (_("register save offset not a multiple of %u"), abs_data_align);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void cfi_add_CFA_register ( unsigned  reg1,
unsigned  reg2 
)

Definition at line 291 of file dw2gencfi.c.

Here is the call graph for this function:

Here is the caller graph for this function:

void cfi_add_CFA_remember_state ( void  )

Definition at line 332 of file dw2gencfi.c.

{
  struct cfa_save_data *p;

  cfi_add_CFA_insn (DW_CFA_remember_state);

  p = xmalloc (sizeof (*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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void cfi_add_CFA_restore ( unsigned  regno)

Definition at line 314 of file dw2gencfi.c.

Here is the call graph for this function:

Here is the caller graph for this function:

void cfi_add_CFA_restore_state ( void  )

Definition at line 345 of file dw2gencfi.c.

{
  struct cfa_save_data *p;

  cfi_add_CFA_insn (DW_CFA_restore_state);

  p = frchain_now->frch_cfi_data->cfa_save_stack;
  if (p)
    {
      frchain_now->frch_cfi_data->cur_cfa_offset = p->cfa_offset;
      frchain_now->frch_cfi_data->cfa_save_stack = p->next;
      free (p);
    }
  else
    as_bad (_("CFI state restore without previous remember"));
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 326 of file dw2gencfi.c.

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 320 of file dw2gencfi.c.

Here is the call graph for this function:

Here is the caller graph for this function:

void cfi_end_fde ( symbolS *  label)

Definition at line 186 of file dw2gencfi.c.

{
  frchain_now->frch_cfi_data->cur_fde_data->end_address = label;
  free (frchain_now->frch_cfi_data);
  frchain_now->frch_cfi_data = NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void cfi_finish ( void  )

Definition at line 1312 of file dw2gencfi.c.

{
  segT cfi_seg;
  struct fde_entry *fde;
  int save_flag_traditional_format;

  if (all_fde_data == 0)
    return;

  /* Open .eh_frame section.  */
  cfi_seg = subseg_new (".eh_frame", 0);
  bfd_set_section_flags (stdoutput, cfi_seg,
                      SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_READONLY);
  subseg_set (cfi_seg, 0);
  record_alignment (cfi_seg, EH_FRAME_ALIGNMENT);

  /* Make sure check_eh_frame doesn't do anything with our output.  */
  save_flag_traditional_format = flag_traditional_format;
  flag_traditional_format = 1;

  for (fde = all_fde_data; fde ; fde = fde->next)
    {
      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);
    }

  flag_traditional_format = save_flag_traditional_format;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void cfi_new_fde ( symbolS *  label)

Definition at line 176 of file dw2gencfi.c.

{
  struct fde_entry *fde = alloc_fde_entry ();
  fde->start_address = label;
  frchain_now->frch_cfi_data->last_address = label;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static offsetT cfi_parse_const ( void  ) [static]

Definition at line 460 of file dw2gencfi.c.

{
  return get_absolute_expression ();
}

Here is the call graph for this function:

Here is the caller graph for this function:

static unsigned cfi_parse_reg ( void  ) [static]

Definition at line 415 of file dw2gencfi.c.

{
  int regno;
  expressionS exp;

#ifdef tc_regname_to_dw2regnum
  SKIP_WHITESPACE ();
  if (is_name_beginner (*input_line_pointer)
      || (*input_line_pointer == '%'
         && is_name_beginner (*++input_line_pointer)))
    {
      char *name, c;

      name = input_line_pointer;
      c = get_symbol_end ();

      if ((regno = tc_regname_to_dw2regnum (name)) < 0)
       {
         as_bad (_("bad register expression"));
         regno = 0;
       }

      *input_line_pointer = c;
      return regno;
    }
#endif

  expression_and_evaluate (&exp);
  switch (exp.X_op)
    {
    case O_register:
    case O_constant:
      regno = exp.X_add_number;
      break;

    default:
      as_bad (_("bad register expression"));
      regno = 0;
      break;
    }

  return regno;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void cfi_parse_separator ( void  ) [static]

Definition at line 405 of file dw2gencfi.c.

{
  SKIP_WHITESPACE ();
  if (*input_line_pointer == ',')
    input_line_pointer++;
  else
    as_bad (_("missing separator"));
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 196 of file dw2gencfi.c.

{
  frchain_now->frch_cfi_data->cur_fde_data->return_column = regno;
}

Here is the caller graph for this function:

static void dot_cfi ( int  arg) [static]

Definition at line 466 of file dw2gencfi.c.

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

Here is the call graph for this function:

static void dot_cfi_endproc ( int  ) [static]
static void dot_cfi_endproc ( int ignored  ATTRIBUTE_UNUSED) [static]

Definition at line 806 of file dw2gencfi.c.

{
  if (frchain_now->frch_cfi_data == NULL)
    {
      as_bad (_(".cfi_endproc without corresponding .cfi_startproc"));
      ignore_rest_of_line ();
      return;
    }

  cfi_end_fde (symbol_temp_new_now ());

  demand_empty_rest_of_line ();
}

Here is the call graph for this function:

static void dot_cfi_escape ( int  ) [static]
static void dot_cfi_escape ( int ignored  ATTRIBUTE_UNUSED) [static]

Definition at line 589 of file dw2gencfi.c.

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

Here is the call graph for this function:

static void dot_cfi_lsda ( int  ) [static]
static void dot_cfi_lsda ( int ignored  ATTRIBUTE_UNUSED) [static]

Definition at line 697 of file dw2gencfi.c.

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

Here is the call graph for this function:

static void dot_cfi_personality ( int  ) [static]
static void dot_cfi_personality ( int ignored  ATTRIBUTE_UNUSED) [static]

Definition at line 627 of file dw2gencfi.c.

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

Here is the call graph for this function:

static void dot_cfi_startproc ( int  ) [static]
static void dot_cfi_startproc ( int ignored  ATTRIBUTE_UNUSED) [static]

Definition at line 769 of file dw2gencfi.c.

{
  int simple = 0;

  if (frchain_now->frch_cfi_data != NULL)
    {
      as_bad (_("previous CFI entry not closed (missing .cfi_endproc)"));
      ignore_rest_of_line ();
      return;
    }

  cfi_new_fde (symbol_temp_new_now ());

  SKIP_WHITESPACE ();
  if (is_name_beginner (*input_line_pointer))
    {
      char *name, c;

      name = input_line_pointer;
      c = get_symbol_end ();

      if (strcmp (name, "simple") == 0)
       {
         simple = 1;
         *input_line_pointer = c;
       }
      else
       input_line_pointer = name;
    }
  demand_empty_rest_of_line ();

  frchain_now->frch_cfi_data->cur_cfa_offset = 0;
  if (!simple)
    tc_cfi_frame_initial_instructions ();
}

Here is the call graph for this function:

static offsetT encoding_size ( unsigned char  encoding) [static]

Definition at line 1020 of file dw2gencfi.c.

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

Here is the call graph for this function:

Here is the caller graph for this function:

static void out_four ( int  data) [inline, static]

Definition at line 840 of file dw2gencfi.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static void out_one ( int  byte) [inline, static]

Definition at line 824 of file dw2gencfi.c.

{
  FRAG_APPEND_1_CHAR (byte);
}

Here is the caller graph for this function:

static void out_sleb128 ( offsetT  value) [static]

Definition at line 856 of file dw2gencfi.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static void out_two ( int  data) [inline, static]

Definition at line 832 of file dw2gencfi.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static void out_uleb128 ( addressT  value) [static]

Definition at line 848 of file dw2gencfi.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static void output_cfi_insn ( struct cfi_insn_data insn) [static]

Definition at line 862 of file dw2gencfi.c.

{
  offsetT offset;
  unsigned int regno;

  switch (insn->insn)
    {
    case DW_CFA_advance_loc:
      {
       symbolS *from = insn->u.ll.lab1;
       symbolS *to = insn->u.ll.lab2;

       if (symbol_get_frag (to) == symbol_get_frag (from))
         {
           addressT delta = S_GET_VALUE (to) - S_GET_VALUE (from);
           addressT scaled = delta / DWARF2_LINE_MIN_INSN_LENGTH;

           if (scaled <= 0x3F)
             out_one (DW_CFA_advance_loc + scaled);
           else if (delta <= 0xFF)
             {
              out_one (DW_CFA_advance_loc1);
              out_one (delta);
             }
           else if (delta <= 0xFFFF)
             {
              out_one (DW_CFA_advance_loc2);
              out_two (delta);
             }
           else
             {
              out_one (DW_CFA_advance_loc4);
              out_four (delta);
             }
         }
       else
         {
           expressionS exp;

           exp.X_op = O_subtract;
           exp.X_add_symbol = to;
           exp.X_op_symbol = from;
           exp.X_add_number = 0;

           /* The code in ehopt.c expects that one byte of the encoding
              is already allocated to the frag.  This comes from the way
              that it scans the .eh_frame section looking first for the
              .byte DW_CFA_advance_loc4.  */
           frag_more (1);

           frag_var (rs_cfa, 4, 0, DWARF2_LINE_MIN_INSN_LENGTH << 3,
                    make_expr_symbol (&exp), frag_now_fix () - 1,
                    (char *) frag_now);
         }
      }
      break;

    case DW_CFA_def_cfa:
      offset = insn->u.ri.offset;
      if (offset < 0)
       {
         out_one (DW_CFA_def_cfa_sf);
         out_uleb128 (insn->u.ri.reg);
         out_sleb128 (offset / DWARF2_CIE_DATA_ALIGNMENT);
       }
      else
       {
         out_one (DW_CFA_def_cfa);
         out_uleb128 (insn->u.ri.reg);
         out_uleb128 (offset);
       }
      break;

    case DW_CFA_def_cfa_register:
    case DW_CFA_undefined:
    case DW_CFA_same_value:
      out_one (insn->insn);
      out_uleb128 (insn->u.r);
      break;

    case DW_CFA_def_cfa_offset:
      offset = insn->u.i;
      if (offset < 0)
       {
         out_one (DW_CFA_def_cfa_offset_sf);
         out_sleb128 (offset / DWARF2_CIE_DATA_ALIGNMENT);
       }
      else
       {
         out_one (DW_CFA_def_cfa_offset);
         out_uleb128 (offset);
       }
      break;

    case DW_CFA_restore:
      regno = insn->u.r;
      if (regno <= 0x3F)
       {
         out_one (DW_CFA_restore + regno);
       }
      else
       {
         out_one (DW_CFA_restore_extended);
         out_uleb128 (regno);
       }
      break;

    case DW_CFA_offset:
      regno = insn->u.ri.reg;
      offset = insn->u.ri.offset / DWARF2_CIE_DATA_ALIGNMENT;
      if (offset < 0)
       {
         out_one (DW_CFA_offset_extended_sf);
         out_uleb128 (regno);
         out_sleb128 (offset);
       }
      else if (regno <= 0x3F)
       {
         out_one (DW_CFA_offset + regno);
         out_uleb128 (offset);
       }
      else
       {
         out_one (DW_CFA_offset_extended);
         out_uleb128 (regno);
         out_uleb128 (offset);
       }
      break;

    case DW_CFA_register:
      out_one (DW_CFA_register);
      out_uleb128 (insn->u.rr.reg1);
      out_uleb128 (insn->u.rr.reg2);
      break;

    case DW_CFA_remember_state:
    case DW_CFA_restore_state:
      out_one (insn->insn);
      break;

    case DW_CFA_GNU_window_save:
      out_one (DW_CFA_GNU_window_save);
      break;

    case CFI_escape:
      {
       struct cfi_escape_data *e;
       for (e = insn->u.esc; e ; e = e->next)
         emit_expr (&e->exp, 1);
       break;
      }

    default:
      abort ();
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void output_cie ( struct cie_entry cie) [static]

Definition at line 1040 of file dw2gencfi.c.

{
  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 ();
  end_address = symbol_temp_make ();

  exp.X_op = O_subtract;
  exp.X_add_symbol = end_address;
  exp.X_op_symbol = after_size_address;
  exp.X_add_number = 0;

  emit_expr (&exp, 4);                           /* Length.  */
  symbol_set_value_now (after_size_address);
  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');
  out_one (0);
  out_uleb128 (DWARF2_LINE_MIN_INSN_LENGTH);     /* Code alignment.  */
  out_sleb128 (DWARF2_CIE_DATA_ALIGNMENT);       /* Data alignment.  */
  if (DW_CIE_VERSION == 1)                /* Return column.  */
    out_one (cie->return_column);
  else
    out_uleb128 (cie->return_column);
  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
  out_one (DW_EH_PE_sdata4);
#endif

  if (cie->first)
    for (i = cie->first; i != cie->last; i = i->next)
      output_cfi_insn (i);

  frag_align (2, DW_CFA_nop, 0);
  symbol_set_value_now (end_address);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void output_fde ( struct fde_entry fde,
struct cie_entry cie,
struct cfi_insn_data first,
int  align 
) [static]

Definition at line 1116 of file dw2gencfi.c.

{
  symbolS *after_size_address, *end_address;
  expressionS exp;
  offsetT augmentation_size;

  after_size_address = symbol_temp_make ();
  end_address = symbol_temp_make ();

  exp.X_op = O_subtract;
  exp.X_add_symbol = end_address;
  exp.X_op_symbol = after_size_address;
  exp.X_add_number = 0;
  emit_expr (&exp, 4);                           /* Length.  */
  symbol_set_value_now (after_size_address);

  exp.X_add_symbol = after_size_address;
  exp.X_op_symbol = cie->start_address;
  emit_expr (&exp, 4);                           /* CIE offset.  */

#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.  */
#else
  exp.X_op = O_symbol;
  exp.X_add_symbol = fde->start_address;
  exp.X_op_symbol = NULL;
#ifdef tc_cfi_emit_pcrel_expr
  tc_cfi_emit_pcrel_expr (&exp, 4);              /* Code offset.  */
#else
  emit_expr (&exp, 4);                           /* Code offset.  */
#endif
  exp.X_op = O_subtract;
#endif

  exp.X_add_symbol = fde->end_address;
  exp.X_op_symbol = fde->start_address;          /* Code length.  */
  emit_expr (&exp, 4);

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

  frag_align (align, DW_CFA_nop, 0);
  symbol_set_value_now (end_address);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static struct cie_entry* select_cie_for_fde ( struct fde_entry fde,
struct cfi_insn_data **  pfirst 
) [static, read]

Definition at line 1187 of file dw2gencfi.c.

{
  struct cfi_insn_data *i, *j;
  struct cie_entry *cie;

  for (cie = cie_root; cie; cie = cie->next)
    {
      if (cie->return_column != fde->return_column
         || 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)
       {
         if (i->insn != j->insn)
           goto fail;
         switch (i->insn)
           {
           case DW_CFA_advance_loc:
           case DW_CFA_remember_state:
             /* We reached the first advance/remember in the FDE,
               but did not reach the end of the CIE list.  */
             goto fail;

           case DW_CFA_offset:
           case DW_CFA_def_cfa:
             if (i->u.ri.reg != j->u.ri.reg)
              goto fail;
             if (i->u.ri.offset != j->u.ri.offset)
              goto fail;
             break;

           case DW_CFA_register:
             if (i->u.rr.reg1 != j->u.rr.reg1)
              goto fail;
             if (i->u.rr.reg2 != j->u.rr.reg2)
              goto fail;
             break;

           case DW_CFA_def_cfa_register:
           case DW_CFA_restore:
           case DW_CFA_undefined:
           case DW_CFA_same_value:
             if (i->u.r != j->u.r)
              goto fail;
             break;

           case DW_CFA_def_cfa_offset:
             if (i->u.i != j->u.i)
              goto fail;
             break;

           case CFI_escape:
             /* Don't bother matching these for now.  */
             goto fail;

           default:
             abort ();
           }
       }

      /* Success if we reached the end of the CIE list, and we've either
        run out of FDE entries or we've encountered an advance,
        remember, or escape.  */
      if (i == cie->last
         && (!j
             || j->insn == DW_CFA_advance_loc
             || j->insn == DW_CFA_remember_state
             || j->insn == CFI_escape))
       {
         *pfirst = j;
         return cie;
       }

    fail:;
    }

  cie = xmalloc (sizeof (struct cie_entry));
  cie->next = cie_root;
  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)
    if (i->insn == DW_CFA_advance_loc
       || i->insn == DW_CFA_remember_state
       || i->insn == CFI_escape)
      break;

  cie->last = i;
  *pfirst = i;
   
  output_cie (cie);

  return cie;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

Definition at line 113 of file dw2gencfi.c.

const pseudo_typeS cfi_pseudo_table[]
Initial value:
  {
    { "cfi_startproc", dot_cfi_startproc, 0 },
    { "cfi_endproc", dot_cfi_endproc, 0 },
    { "cfi_def_cfa", dot_cfi, DW_CFA_def_cfa },
    { "cfi_def_cfa_register", dot_cfi, DW_CFA_def_cfa_register },
    { "cfi_def_cfa_offset", dot_cfi, DW_CFA_def_cfa_offset },
    { "cfi_adjust_cfa_offset", dot_cfi, CFI_adjust_cfa_offset },
    { "cfi_offset", dot_cfi, DW_CFA_offset },
    { "cfi_rel_offset", dot_cfi, CFI_rel_offset },
    { "cfi_register", dot_cfi, DW_CFA_register },
    { "cfi_return_column", dot_cfi, CFI_return_column },
    { "cfi_restore", dot_cfi, DW_CFA_restore },
    { "cfi_undefined", dot_cfi, DW_CFA_undefined },
    { "cfi_same_value", dot_cfi, DW_CFA_same_value },
    { "cfi_remember_state", dot_cfi, DW_CFA_remember_state },
    { "cfi_restore_state", dot_cfi, DW_CFA_restore_state },
    { "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 },
    { NULL, NULL, 0 }
  }

Definition at line 379 of file dw2gencfi.c.

Definition at line 117 of file dw2gencfi.c.

Definition at line 114 of file dw2gencfi.c.