/* dw2gencfi.c - Support for generating Dwarf2 CFI information.
- Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Contributed by Michal Ludvig <mludvig@suse.cz>
# endif
#endif
+#ifndef CFI_DIFF_LSDA_OK
+# define CFI_DIFF_LSDA_OK CFI_DIFF_EXPR_OK
+#endif
+
+#if CFI_DIFF_EXPR_OK == 1 && CFI_DIFF_LSDA_OK == 0
+# error "CFI_DIFF_EXPR_OK should imply CFI_DIFF_LSDA_OK"
+#endif
+
/* We re-use DWARF2_LINE_MIN_INSN_LENGTH for the code alignment field
of the CIE. Default to 1 if not otherwise specified. */
#ifndef DWARF2_LINE_MIN_INSN_LENGTH
# define DWARF2_ADDR_SIZE(bfd) (bfd_arch_bits_per_address (bfd) / 8)
#endif
+/* ??? Share this with dwarf2cfg.c. */
+#ifndef TC_DWARF2_EMIT_OFFSET
+#define TC_DWARF2_EMIT_OFFSET generic_dwarf2_emit_offset
+
+/* Create an offset to .dwarf2_*. */
+
+static void
+generic_dwarf2_emit_offset (symbolS *symbol, unsigned int size)
+{
+ expressionS exp;
+
+ exp.X_op = O_symbol;
+ exp.X_add_symbol = symbol;
+ exp.X_add_number = 0;
+ emit_expr (&exp, size);
+}
+#endif
+
struct cfi_escape_data {
struct cfi_escape_data *next;
expressionS exp;
if ((encoding & 0xff) != encoding
|| ((encoding & 0x70) != 0
-#if CFI_DIFF_EXPR_OK || defined tc_cfi_emit_pcrel_expr
+#if CFI_DIFF_LSDA_OK || defined tc_cfi_emit_pcrel_expr
&& (encoding & 0x70) != DW_EH_PE_pcrel
#endif
)
if (cie->lsda_encoding != DW_EH_PE_omit)
out_one ('L');
out_one ('R');
- if (cie->signal_frame)
- out_one ('S');
}
+ 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 (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)
+
+ 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)
+ {
#if CFI_DIFF_EXPR_OK
- exp.X_op = O_subtract;
- exp.X_op_symbol = symbol_temp_new_now ();
- emit_expr (&exp, size);
+ 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);
+ tc_cfi_emit_pcrel_expr (&exp, size);
#else
- abort ();
+ abort ();
#endif
+ }
+ else
+ emit_expr (&exp, size);
}
- else
- emit_expr (&exp, size);
+
+ if (cie->lsda_encoding != DW_EH_PE_omit)
+ out_one (cie->lsda_encoding);
}
- if (cie->lsda_encoding != DW_EH_PE_omit)
- out_one (cie->lsda_encoding);
switch (DWARF2_FDE_RELOC_SIZE)
{
if (eh_frame)
{
+ exp.X_op = O_subtract;
exp.X_add_symbol = after_size_address;
exp.X_op_symbol = cie->start_address;
+ exp.X_add_number = 0;
+ emit_expr (&exp, offset_size); /* CIE offset. */
}
else
{
- exp.X_op = O_symbol;
- exp.X_add_symbol = cie->start_address;
- exp.X_op_symbol = NULL;
+ TC_DWARF2_EMIT_OFFSET (cie->start_address, offset_size);
}
- emit_expr (&exp, offset_size); /* CIE offset. */
if (eh_frame)
{
+ exp.X_op = O_subtract;
+ exp.X_add_number = 0;
#if CFI_DIFF_EXPR_OK
exp.X_add_symbol = fde->start_address;
exp.X_op_symbol = symbol_temp_new_now ();
#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, DWARF2_FDE_RELOC_SIZE); /* Code offset. */
#else
}
else
{
+ exp.X_op = O_symbol;
exp.X_add_symbol = fde->start_address;
+ exp.X_add_number = 0;
addr_size = DWARF2_ADDR_SIZE (stdoutput);
emit_expr (&exp, addr_size);
}
exp.X_op = O_subtract;
exp.X_add_symbol = fde->end_address;
exp.X_op_symbol = fde->start_address; /* Code length. */
+ exp.X_add_number = 0;
emit_expr (&exp, addr_size);
augmentation_size = encoding_size (fde->lsda_encoding);
exp = fde->lsda;
if ((fde->lsda_encoding & 0x70) == DW_EH_PE_pcrel)
{
-#if CFI_DIFF_EXPR_OK
+#if CFI_DIFF_LSDA_OK
exp.X_op = O_subtract;
exp.X_op_symbol = symbol_temp_new_now ();
emit_expr (&exp, augmentation_size);
for (fde = all_fde_data; fde ; fde = fde->next)
{
struct cfi_insn_data *first;
- struct cie_entry *cie;
if (fde->end_address == NULL)
{
}
#else /* TARGET_USE_CFIPOP */
+
+/* Emit an intelligible error message for missing support. */
+
+static void
+dot_cfi_dummy (int ignored ATTRIBUTE_UNUSED)
+{
+ as_bad (_("CFI is not supported for this target"));
+ ignore_rest_of_line ();
+}
+
+const pseudo_typeS cfi_pseudo_table[] =
+ {
+ { "cfi_sections", dot_cfi_dummy, 0 },
+ { "cfi_startproc", dot_cfi_dummy, 0 },
+ { "cfi_endproc", dot_cfi_dummy, 0 },
+ { "cfi_def_cfa", dot_cfi_dummy, 0 },
+ { "cfi_def_cfa_register", dot_cfi_dummy, 0 },
+ { "cfi_def_cfa_offset", dot_cfi_dummy, 0 },
+ { "cfi_adjust_cfa_offset", dot_cfi_dummy, 0 },
+ { "cfi_offset", dot_cfi_dummy, 0 },
+ { "cfi_rel_offset", dot_cfi_dummy, 0 },
+ { "cfi_register", dot_cfi_dummy, 0 },
+ { "cfi_return_column", dot_cfi_dummy, 0 },
+ { "cfi_restore", dot_cfi_dummy, 0 },
+ { "cfi_undefined", dot_cfi_dummy, 0 },
+ { "cfi_same_value", dot_cfi_dummy, 0 },
+ { "cfi_remember_state", dot_cfi_dummy, 0 },
+ { "cfi_restore_state", dot_cfi_dummy, 0 },
+ { "cfi_window_save", dot_cfi_dummy, 0 },
+ { "cfi_escape", dot_cfi_dummy, 0 },
+ { "cfi_signal_frame", dot_cfi_dummy, 0 },
+ { "cfi_personality", dot_cfi_dummy, 0 },
+ { "cfi_lsda", dot_cfi_dummy, 0 },
+ { "cfi_val_encoded_addr", dot_cfi_dummy, 0 },
+ { NULL, NULL, 0 }
+ };
+
void
cfi_finish (void)
{