diff options
author | Richard Henderson <rth@redhat.com> | 2003-06-08 03:59:44 +0000 |
---|---|---|
committer | Richard Henderson <rth@redhat.com> | 2003-06-08 03:59:44 +0000 |
commit | fa87b337c32686ec4526ea03e3041737ebdeb9f0 (patch) | |
tree | 7b507e8b570fbdc12d4a02ff4318cdda18ef5d5b /gas/dw2gencfi.c | |
parent | a0273b2f038b41d2903dbfa48048d83d5c4291fc (diff) | |
download | gdb-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.c | 41 |
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 (); |