/* dw2gencfi.c - Support for generating Dwarf2 CFI information.
- Copyright (C) 2003-2014 Free Software Foundation, Inc.
+ Copyright (C) 2003-2015 Free Software Foundation, Inc.
Contributed by Michal Ludvig <mludvig@suse.cz>
This file is part of GAS, the GNU Assembler.
else
flags = bfd_get_section_flags (stdoutput, cseg)
& (SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD
- | SEC_LINK_DUPLICATES_ONE_ONLY | SEC_LINK_DUPLICATES_SAME_SIZE
- | SEC_LINK_DUPLICATES_SAME_CONTENTS);
+ | SEC_LINK_DUPLICATES_ONE_ONLY | SEC_LINK_DUPLICATES_SAME_SIZE
+ | SEC_LINK_DUPLICATES_SAME_CONTENTS);
/* Add standard section flags. */
flags |= sflags;
frchain_now->frch_cfi_data->last_address = label;
}
+/* Add a CFI insn to label the current position in the CFI segment. */
+
+void
+cfi_add_label (const char *name)
+{
+ unsigned int len = strlen (name) + 1;
+ struct cfi_insn_data *insn = alloc_cfi_insn_data ();
+
+ insn->insn = CFI_label;
+ obstack_grow (¬es, name, len);
+ insn->u.sym_name = (char *) obstack_finish (¬es);
+}
+
/* Add a DW_CFA_offset record to the CFI data. */
void
static void dot_cfi_personality (int);
static void dot_cfi_lsda (int);
static void dot_cfi_val_encoded_addr (int);
+static void dot_cfi_label (int);
const pseudo_typeS cfi_pseudo_table[] =
{
{ "cfi_personality", dot_cfi_personality, 0 },
{ "cfi_lsda", dot_cfi_lsda, 0 },
{ "cfi_val_encoded_addr", dot_cfi_val_encoded_addr, 0 },
+ { "cfi_label", dot_cfi_label, 0 },
{ NULL, NULL, 0 }
};
break;
case O_constant:
if ((encoding & 0x70) != DW_EH_PE_pcrel)
- break;
+ break;
default:
encoding = DW_EH_PE_omit;
break;
demand_empty_rest_of_line ();
}
+static void
+dot_cfi_label (int ignored ATTRIBUTE_UNUSED)
+{
+ char *name = read_symbol_name ();
+
+ if (name == NULL)
+ 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 ());
+
+ cfi_add_label (name);
+
+ demand_empty_rest_of_line ();
+}
+
/* By default emit .eh_frame only, not .debug_frame. */
#define CFI_EMIT_eh_frame (1 << 0)
#define CFI_EMIT_debug_frame (1 << 1)
case CFI_val_encoded_addr:
{
- unsigned encoding = insn->u.ea.encoding;
- offsetT encoding_size;
+ unsigned encoding = insn->u.ea.encoding;
+ offsetT encoding_size;
if (encoding == DW_EH_PE_omit)
break;
out_one (DW_CFA_val_expression);
out_uleb128 (insn->u.ea.reg);
- switch (encoding & 0x7)
+ switch (encoding & 0x7)
{
case DW_EH_PE_absptr:
encoding_size = DWARF2_ADDR_SIZE (stdoutput);
}
break;
+ case CFI_label:
+ colon (insn->u.sym_name);
+ break;
+
default:
abort ();
}
if (cie->first)
{
for (i = cie->first; i != cie->last; i = i->next)
- {
+ {
if (CUR_SEG (i) != CUR_SEG (cie))
continue;
output_cfi_insn (i);
case CFI_escape:
case CFI_val_encoded_addr:
+ case CFI_label:
/* Don't bother matching these for now. */
goto fail;
|| j->insn == DW_CFA_advance_loc
|| j->insn == DW_CFA_remember_state
|| j->insn == CFI_escape
- || j->insn == CFI_val_encoded_addr))
+ || j->insn == CFI_val_encoded_addr
+ || j->insn == CFI_label))
{
*pfirst = j;
return cie;
if (i->insn == DW_CFA_advance_loc
|| i->insn == DW_CFA_remember_state
|| i->insn == CFI_escape
- || i->insn == CFI_val_encoded_addr)
+ || i->insn == CFI_val_encoded_addr
+ || i->insn == CFI_label)
break;
cie->last = i;
for (; insn; insn = insn->next)
{
if (CUR_SEG (insn) != ccseg)
- continue;
+ continue;
switch (insn->insn)
{
case DW_CFA_advance_loc:
case DW_CFA_restore_state:
case DW_CFA_GNU_window_save:
case CFI_escape:
+ case CFI_label:
break;
case DW_CFA_def_cfa:
}
do
- {
+ {
ccseg = NULL;
seek_next_seg = 0;
alignment);
do
- {
+ {
ccseg = NULL;
seek_next_seg = 0;
{ "cfi_personality", dot_cfi_dummy, 0 },
{ "cfi_lsda", dot_cfi_dummy, 0 },
{ "cfi_val_encoded_addr", dot_cfi_dummy, 0 },
+ { "cfi_label", dot_cfi_dummy, 0 },
{ NULL, NULL, 0 }
};