aboutsummaryrefslogtreecommitdiff
path: root/gas/dw2gencfi.c
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2003-06-08 03:59:44 +0000
committerRichard Henderson <rth@redhat.com>2003-06-08 03:59:44 +0000
commitfa87b337c32686ec4526ea03e3041737ebdeb9f0 (patch)
tree7b507e8b570fbdc12d4a02ff4318cdda18ef5d5b /gas/dw2gencfi.c
parenta0273b2f038b41d2903dbfa48048d83d5c4291fc (diff)
downloadgdb-fa87b337c32686ec4526ea03e3041737ebdeb9f0.zip
gdb-fa87b337c32686ec4526ea03e3041737ebdeb9f0.tar.gz
gdb-fa87b337c32686ec4526ea03e3041737ebdeb9f0.tar.bz2
* dw2gencfi.c (struct cfa_save_data, cfa_save_stack): New.
(cfi_add_CFA_offset): Detect invalid offsets. (cfi_add_CFA_remember_state): Save cur_cfa_offset. (cfi_add_CFA_restore_state): Restore it. (CFI_rel_offset): New. (cfi_pseudo_table): Add it. (dot_cfi): Handle it. * gas/cfi/cfi-common-1.d, gas/cfi/cfi-common-1.s: New. * gas/cfi/cfi-common-2.d, gas/cfi/cfi-common-2.s: New. * gas/cfi/cfi-diag-1.d, gas/cfi/cfi-diag-1.s: New. * gas/cfi/cfi.exp: Run them.
Diffstat (limited to 'gas/dw2gencfi.c')
-rw-r--r--gas/dw2gencfi.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/gas/dw2gencfi.c b/gas/dw2gencfi.c
index 5e37833..ccfb110 100644
--- a/gas/dw2gencfi.c
+++ b/gas/dw2gencfi.c
@@ -102,6 +102,14 @@ static struct fde_entry **last_fde_data = &all_fde_data;
/* List of CIEs so that they could be reused. */
static struct cie_entry *cie_root;
+/* Stack of old CFI data, for save/restore. */
+struct cfa_save_data
+{
+ struct cfa_save_data *next;
+ offsetT cfa_offset;
+};
+
+static struct cfa_save_data *cfa_save_stack;
/* Construct a new FDE structure and add it to the end of the fde list. */
@@ -231,7 +239,14 @@ cfi_add_advance_loc (symbolS *label)
void
cfi_add_CFA_offset (unsigned regno, offsetT offset)
{
+ unsigned int abs_data_align;
+
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);
}
/* Add a DW_CFA_def_cfa record to the CFI data. */
@@ -289,13 +304,30 @@ cfi_add_CFA_same_value (unsigned regno)
void
cfi_add_CFA_remember_state (void)
{
+ struct cfa_save_data *p;
+
cfi_add_CFA_insn (DW_CFA_remember_state);
+
+ p = xmalloc (sizeof (*p));
+ p->cfa_offset = cur_cfa_offset;
+ p->next = cfa_save_stack;
+ cfa_save_stack = p;
}
void
cfi_add_CFA_restore_state (void)
{
+ struct cfa_save_data *p;
+
cfi_add_CFA_insn (DW_CFA_restore_state);
+
+ p = cfa_save_stack;
+ if (p)
+ {
+ cur_cfa_offset = p->cfa_offset;
+ cfa_save_stack = p->next;
+ free (p);
+ }
}
void
@@ -314,6 +346,7 @@ static void dot_cfi_endproc (int);
/* Fake CFI type; outside the byte range of any real CFI insn. */
#define CFI_adjust_cfa_offset 0x100
#define CFI_return_column 0x101
+#define CFI_rel_offset 0x102
const pseudo_typeS cfi_pseudo_table[] =
{
@@ -324,6 +357,7 @@ const pseudo_typeS cfi_pseudo_table[] =
{ "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 },
@@ -422,6 +456,13 @@ dot_cfi (int arg)
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 - cur_cfa_offset);
+ break;
+
case DW_CFA_def_cfa:
reg1 = cfi_parse_reg ();
cfi_parse_separator ();