From: Richard Henderson Date: Sun, 8 Jun 2003 03:59:44 +0000 (+0000) Subject: * dw2gencfi.c (struct cfa_save_data, cfa_save_stack): New. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=fa87b337c32686ec4526ea03e3041737ebdeb9f0;p=binutils-gdb.git * 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. --- diff --git a/gas/ChangeLog b/gas/ChangeLog index 8f5aa936130..799898f96df 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,13 @@ +2003-06-07 Richard Henderson + + * 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. + 2003-06-07 H.J. Lu * app.c (do_scrub_chars): Add states 14 and 15 to handle diff --git a/gas/dw2gencfi.c b/gas/dw2gencfi.c index 5e378337e32..ccfb1103a16 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 (); diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index 665da6ae20a..6d895a050bb 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2003-06-07 Richard Henderson + + * 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. + 2003-06-05 Michael Snyder * gas/h8300/t01_mov.s: New file, tests mov instructions. diff --git a/gas/testsuite/gas/cfi/cfi-common-1.d b/gas/testsuite/gas/cfi/cfi-common-1.d new file mode 100644 index 00000000000..8e7db37f750 --- /dev/null +++ b/gas/testsuite/gas/cfi/cfi-common-1.d @@ -0,0 +1,24 @@ +#readelf: -wf +#name: CFI common 1 +The section .eh_frame contains: + +00000000 00000010 00000000 CIE + Version: 1 + Augmentation: "zR" + Code alignment factor: .* + Data alignment factor: .* + Return address column: .* + Augmentation data: 1b + + DW_CFA_nop + DW_CFA_nop + DW_CFA_nop + +00000014 00000018 00000018 FDE cie=00000000 pc=.* + DW_CFA_advance_loc: 4 to .* + DW_CFA_def_cfa: r0 ofs 16 + DW_CFA_offset: r1 at cfa-8 + DW_CFA_advance_loc: 4 to .* + DW_CFA_def_cfa_offset: 32 + DW_CFA_offset: r2 at cfa-24 + diff --git a/gas/testsuite/gas/cfi/cfi-common-1.s b/gas/testsuite/gas/cfi/cfi-common-1.s new file mode 100644 index 00000000000..72db279ecea --- /dev/null +++ b/gas/testsuite/gas/cfi/cfi-common-1.s @@ -0,0 +1,8 @@ + .cfi_startproc simple + .long 0 + .cfi_def_cfa 0, 16 + .cfi_rel_offset 1, 8 + .long 0 + .cfi_adjust_cfa_offset 16 + .cfi_rel_offset 2, 8 + .cfi_endproc diff --git a/gas/testsuite/gas/cfi/cfi-common-2.d b/gas/testsuite/gas/cfi/cfi-common-2.d new file mode 100644 index 00000000000..03f0d883b4b --- /dev/null +++ b/gas/testsuite/gas/cfi/cfi-common-2.d @@ -0,0 +1,29 @@ +#readelf: -wf +#name: CFI common 2 +The section .eh_frame contains: + +00000000 00000010 00000000 CIE + Version: 1 + Augmentation: "zR" + Code alignment factor: .* + Data alignment factor: .* + Return address column: .* + Augmentation data: 1b + + DW_CFA_nop + DW_CFA_nop + DW_CFA_nop + +00000014 0000001c 00000018 FDE cie=00000000 pc=.* + DW_CFA_advance_loc: 4 to .* + DW_CFA_def_cfa: r0 ofs 16 + DW_CFA_advance_loc: 4 to .* + DW_CFA_remember_state + DW_CFA_advance_loc: 4 to .* + DW_CFA_def_cfa_offset: 0 + DW_CFA_advance_loc: 4 to .* + DW_CFA_restore_state + DW_CFA_advance_loc: 4 to .* + DW_CFA_def_cfa_offset: 0 + DW_CFA_nop + diff --git a/gas/testsuite/gas/cfi/cfi-common-2.s b/gas/testsuite/gas/cfi/cfi-common-2.s new file mode 100644 index 00000000000..e2a94430295 --- /dev/null +++ b/gas/testsuite/gas/cfi/cfi-common-2.s @@ -0,0 +1,12 @@ + .cfi_startproc simple + .long 0 + .cfi_def_cfa 0, 16 + .long 0 + .cfi_remember_state + .long 0 + .cfi_adjust_cfa_offset -16 + .long 0 + .cfi_restore_state + .long 0 + .cfi_adjust_cfa_offset -16 + .cfi_endproc diff --git a/gas/testsuite/gas/cfi/cfi-diag-1.l b/gas/testsuite/gas/cfi/cfi-diag-1.l new file mode 100644 index 00000000000..3dc8a615cff --- /dev/null +++ b/gas/testsuite/gas/cfi/cfi-diag-1.l @@ -0,0 +1,2 @@ +.*: Assembler messages: +.*:2: Error: register save offset not a multiple of .* diff --git a/gas/testsuite/gas/cfi/cfi-diag-1.s b/gas/testsuite/gas/cfi/cfi-diag-1.s new file mode 100644 index 00000000000..de0f8654e8c --- /dev/null +++ b/gas/testsuite/gas/cfi/cfi-diag-1.s @@ -0,0 +1,3 @@ + .cfi_startproc + .cfi_offset 0, 1 + .cfi_endproc diff --git a/gas/testsuite/gas/cfi/cfi.exp b/gas/testsuite/gas/cfi/cfi.exp index 0c24682ff36..88baac25150 100644 --- a/gas/testsuite/gas/cfi/cfi.exp +++ b/gas/testsuite/gas/cfi/cfi.exp @@ -1,9 +1,27 @@ +# ??? This probably shouldn't be replicated here... +proc run_list_test { name opts } { + global srcdir subdir + set testname "cfi $name" + set file $srcdir/$subdir/$name + gas_run ${name}.s $opts ">&dump.out" + if { [regexp_diff "dump.out" "${file}.l"] } then { + fail $testname + verbose "output is [file_contents "dump.out"]" 2 + return + } + pass $testname +} + +set any "0" + if [istarget "x86_64-*"] then { run_dump_test "cfi-x86_64" + set any "1" } if [istarget "i?86-*"] then { run_dump_test "cfi-i386" + set any "1" } if { [istarget alpha*-*-*] } then { @@ -17,5 +35,12 @@ if { [istarget alpha*-*-*] } then { run_dump_test "cfi-alpha-1" run_dump_test "cfi-alpha-2" run_dump_test "cfi-alpha-3" + set any "1" } } + +if $any { + run_list_test "cfi-diag-1" "" + run_dump_test "cfi-common-1" + run_dump_test "cfi-common-2" +}