This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
3 dw2gencfi tweeks
- From: Richard Henderson <rth at redhat dot com>
- To: binutils at sources dot redhat dot com
- Date: Sat, 7 Jun 2003 21:10:55 -0700
- Subject: 3 dw2gencfi tweeks
(1) .cfi_remember_state/.cfi_restore_state didn't work as I'd
have expected. Namely, we didn't remember the cfa offset
across the push/pop, which make it sort of confusing to
use .cfi_adjust_cfa_offset.
(2) Data offsets not a multiple of the divisor were not detected,
This leads to descriptions that are not what the user intended.
I suppose a more user-friendly course of action would be to
choose a gcd from the set of all offsets actually used. This
might lead to more compact codes based on being able to use
DW_CFA_offset more often than DW_CFA_offset_extended. However,
that seems like a lot of work, and I seriously doubt that
someone is *actually* going to be storing a register at an odd
offset. That just seems like a typo to me.
(3) Uli pointed out that .cfi_offset isn't particularly easy to use.
One has to remember the current CFA offset. Which is silly
because we've got this handy .cfi_adjust_cfa_offset directive.
So this adds a .cfi_rel_offset directive that's relative to the
current CFA offset.
Tests for all three of these included.
r~
* 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.
Index: dw2gencfi.c
===================================================================
RCS file: /cvs/src/src/gas/dw2gencfi.c,v
retrieving revision 1.10
diff -c -p -d -u -r1.10 dw2gencfi.c
--- dw2gencfi.c 5 Jun 2003 09:23:47 -0000 1.10
+++ dw2gencfi.c 8 Jun 2003 03:55:05 -0000
@@ -102,6 +102,14 @@ static struct fde_entry **last_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 },
@@ -420,6 +454,13 @@ dot_cfi (int arg)
cfi_parse_separator ();
offset = cfi_parse_const ();
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:
Index: testsuite/gas/cfi/cfi-common-1.d
===================================================================
RCS file: testsuite/gas/cfi/cfi-common-1.d
diff -N testsuite/gas/cfi/cfi-common-1.d
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ testsuite/gas/cfi/cfi-common-1.d 8 Jun 2003 03:55:05 -0000
@@ -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
+
Index: testsuite/gas/cfi/cfi-common-1.s
===================================================================
RCS file: testsuite/gas/cfi/cfi-common-1.s
diff -N testsuite/gas/cfi/cfi-common-1.s
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ testsuite/gas/cfi/cfi-common-1.s 8 Jun 2003 03:55:05 -0000
@@ -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
Index: testsuite/gas/cfi/cfi-common-2.d
===================================================================
RCS file: testsuite/gas/cfi/cfi-common-2.d
diff -N testsuite/gas/cfi/cfi-common-2.d
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ testsuite/gas/cfi/cfi-common-2.d 8 Jun 2003 03:55:05 -0000
@@ -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
+
Index: testsuite/gas/cfi/cfi-common-2.s
===================================================================
RCS file: testsuite/gas/cfi/cfi-common-2.s
diff -N testsuite/gas/cfi/cfi-common-2.s
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ testsuite/gas/cfi/cfi-common-2.s 8 Jun 2003 03:55:05 -0000
@@ -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
Index: testsuite/gas/cfi/cfi-diag-1.l
===================================================================
RCS file: testsuite/gas/cfi/cfi-diag-1.l
diff -N testsuite/gas/cfi/cfi-diag-1.l
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ testsuite/gas/cfi/cfi-diag-1.l 8 Jun 2003 03:55:05 -0000
@@ -0,0 +1,2 @@
+.*: Assembler messages:
+.*:2: Error: register save offset not a multiple of .*
Index: testsuite/gas/cfi/cfi-diag-1.s
===================================================================
RCS file: testsuite/gas/cfi/cfi-diag-1.s
diff -N testsuite/gas/cfi/cfi-diag-1.s
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ testsuite/gas/cfi/cfi-diag-1.s 8 Jun 2003 03:55:05 -0000
@@ -0,0 +1,3 @@
+ .cfi_startproc
+ .cfi_offset 0, 1
+ .cfi_endproc
Index: testsuite/gas/cfi/cfi.exp
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/cfi/cfi.exp,v
retrieving revision 1.4
diff -c -p -d -u -r1.4 cfi.exp
--- testsuite/gas/cfi/cfi.exp 5 Jun 2003 03:27:03 -0000 1.4
+++ testsuite/gas/cfi/cfi.exp 8 Jun 2003 03:55:05 -0000
@@ -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"
}