aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gas/ChangeLog13
-rw-r--r--gas/doc/as.texinfo14
-rw-r--r--gas/dw2gencfi.c65
-rw-r--r--gas/dw2gencfi.h1
-rw-r--r--gas/read.c7
-rw-r--r--gas/read.h1
-rw-r--r--gas/testsuite/ChangeLog5
-rw-r--r--gas/testsuite/gas/cfi/cfi-common-3.d21
-rw-r--r--gas/testsuite/gas/cfi/cfi-common-3.s4
-rw-r--r--gas/testsuite/gas/cfi/cfi.exp1
10 files changed, 110 insertions, 22 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 38430a3..9df96ef 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,16 @@
+2003-06-11 Richard Henderson <rth@redhat.com>
+
+ * dw2gencfi.c (struct cfi_escape_data): New.
+ (cfi_add_CFA_nop): Remove.
+ (CFI_escape, dot_cfi_escape): New.
+ (dot_cfi): Remove nop.
+ (cfi_pseudo_table): Remove nop; add escape.
+ (output_cfi_insn): Likewise.
+ (select_cie_for_fde): Stop on escape.
+ * dw2gencfi.h (cfi_add_CFA_nop): Remove.
+ * read.c, read.h (do_parse_cons_expression): New.
+ * doc/as.texinfo (.cfi_escape): New.
+
2003-06-11 Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de>
* config/tc-mips.c (s_cpsetup): Use mips_frame_reg instead of SP.
diff --git a/gas/doc/as.texinfo b/gas/doc/as.texinfo
index d37198a..3e608d4 100644
--- a/gas/doc/as.texinfo
+++ b/gas/doc/as.texinfo
@@ -3691,13 +3691,7 @@ Some machine configurations provide additional directives.
* Byte:: @code{.byte @var{expressions}}
* Comm:: @code{.comm @var{symbol} , @var{length} }
-* CFI directives:: @code{.cfi_startproc}
- @code{.cfi_endproc}
- @code{.cfi_def_cfa @var{register}, @var{offset}}
- @code{.cfi_def_cfa_register @var{register}}
- @code{.cfi_def_cfa_offset @var{offset}}
- @code{.cfi_adjust_cfa_offset @var{offset}}
- @code{.cfi_offset @var{register}, @var{offset}}
+* CFI directives:: @code{.cfi_startproc}, @code{.cfi_endproc}, etc.
* Data:: @code{.data @var{subsection}}
@ifset COFF
@@ -4020,8 +4014,10 @@ using the known displacement of the CFA register from the CFA.
This is often easier to use, because the number will match the
code it's annotating.
-@node Comm
-@section @code{.comm @var{symbol} , @var{length} }
+@section @code{.cfi_escape} @var{expression}[, @dots{}]
+Allows the user to add arbitrary bytes to the unwind info. One
+might use this to add OS-specific CFI opcodes, or generic CFI
+opcodes that GAS does not yet support.
@cindex @code{comm} directive
@cindex symbol, common
diff --git a/gas/dw2gencfi.c b/gas/dw2gencfi.c
index ccfb110..0e118e1 100644
--- a/gas/dw2gencfi.c
+++ b/gas/dw2gencfi.c
@@ -68,6 +68,11 @@ struct cfi_insn_data
symbolS *lab1;
symbolS *lab2;
} ll;
+
+ struct cfi_escape_data {
+ struct cfi_escape_data *next;
+ expressionS exp;
+ } *esc;
} u;
};
@@ -330,16 +335,11 @@ cfi_add_CFA_restore_state (void)
}
}
-void
-cfi_add_CFA_nop (void)
-{
- cfi_add_CFA_insn (DW_CFA_nop);
-}
-
/* Parse CFI assembler directives. */
static void dot_cfi (int);
+static void dot_cfi_escape (int);
static void dot_cfi_startproc (int);
static void dot_cfi_endproc (int);
@@ -347,6 +347,7 @@ static void dot_cfi_endproc (int);
#define CFI_adjust_cfa_offset 0x100
#define CFI_return_column 0x101
#define CFI_rel_offset 0x102
+#define CFI_escape 0x103
const pseudo_typeS cfi_pseudo_table[] =
{
@@ -365,7 +366,7 @@ const pseudo_typeS cfi_pseudo_table[] =
{ "cfi_same_value", dot_cfi, DW_CFA_same_value },
{ "cfi_remember_state", dot_cfi, DW_CFA_remember_state },
{ "cfi_restore_state", dot_cfi, DW_CFA_restore_state },
- { "cfi_nop", dot_cfi, DW_CFA_nop },
+ { "cfi_escape", dot_cfi_escape, 0 },
{ NULL, NULL, 0 }
};
@@ -520,10 +521,6 @@ dot_cfi (int arg)
cfi_add_CFA_restore_state ();
break;
- case DW_CFA_nop:
- cfi_add_CFA_nop ();
- break;
-
default:
abort ();
}
@@ -532,6 +529,39 @@ dot_cfi (int arg)
}
static void
+dot_cfi_escape (int ignored ATTRIBUTE_UNUSED)
+{
+ struct cfi_escape_data *head, **tail, *e;
+ struct cfi_insn_data *insn;
+
+ if (!cur_fde_data)
+ {
+ as_bad (_("CFI instruction used without previous .cfi_startproc"));
+ return;
+ }
+
+ /* If the last address was not at the current PC, advance to current. */
+ if (symbol_get_frag (last_address) != frag_now
+ || S_GET_VALUE (last_address) != frag_now_fix ())
+ cfi_add_advance_loc (symbol_temp_new_now ());
+
+ tail = &head;
+ do
+ {
+ e = xmalloc (sizeof (*e));
+ do_parse_cons_expression (&e->exp, 1);
+ *tail = e;
+ tail = &e->next;
+ }
+ while (*input_line_pointer++ == ',');
+ *tail = NULL;
+
+ insn = alloc_cfi_insn_data ();
+ insn->insn = CFI_escape;
+ insn->u.esc = head;
+}
+
+static void
dot_cfi_startproc (int ignored ATTRIBUTE_UNUSED)
{
int simple = 0;
@@ -757,10 +787,17 @@ output_cfi_insn (struct cfi_insn_data *insn)
case DW_CFA_remember_state:
case DW_CFA_restore_state:
- case DW_CFA_nop:
out_one (insn->insn);
break;
+ case CFI_escape:
+ {
+ struct cfi_escape_data *e;
+ for (e = insn->u.esc; e ; e = e->next)
+ emit_expr (&e->exp, 1);
+ break;
+ }
+
default:
abort ();
}
@@ -892,6 +929,10 @@ select_cie_for_fde (struct fde_entry *fde, struct cfi_insn_data **pfirst)
goto fail;
break;
+ case CFI_escape:
+ /* Don't bother matching these for now. */
+ goto fail;
+
default:
abort ();
}
diff --git a/gas/dw2gencfi.h b/gas/dw2gencfi.h
index 0361f97..75b6ec2 100644
--- a/gas/dw2gencfi.h
+++ b/gas/dw2gencfi.h
@@ -48,6 +48,5 @@ extern void cfi_add_CFA_undefined (unsigned);
extern void cfi_add_CFA_same_value (unsigned);
extern void cfi_add_CFA_remember_state (void);
extern void cfi_add_CFA_restore_state (void);
-extern void cfi_add_CFA_nop (void);
#endif /* DW2GENCFI_H */
diff --git a/gas/read.c b/gas/read.c
index b7d9190..061dfd4 100644
--- a/gas/read.c
+++ b/gas/read.c
@@ -3346,6 +3346,13 @@ parse_repeat_cons PARAMS ((expressionS *exp, unsigned int nbytes));
#endif
#endif
+void
+do_parse_cons_expression (expressionS *exp, int nbytes)
+{
+ TC_PARSE_CONS_EXPRESSION (exp, nbytes);
+}
+
+
/* Worker to do .byte etc statements.
Clobbers input_line_pointer and checks end-of-line. */
diff --git a/gas/read.h b/gas/read.h
index ba431af..5a33c70 100644
--- a/gas/read.h
+++ b/gas/read.h
@@ -133,6 +133,7 @@ extern void stabs_generate_asm_func PARAMS ((const char *, const char *));
extern void stabs_generate_asm_endfunc PARAMS ((const char *, const char *));
extern void do_repeat PARAMS((int,const char *,const char *));
extern void end_repeat PARAMS((int));
+extern void do_parse_cons_expression PARAMS ((expressionS *, int));
extern void generate_lineno_debug PARAMS ((void));
diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog
index d114c0f..1ef04ab 100644
--- a/gas/testsuite/ChangeLog
+++ b/gas/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2003-06-11 Richard Henderson <rth@redhat.com>
+
+ * gas/cfi/cfi-common-3.[ds]: New.
+ * gas/cfi/cfi.exp: Run it.
+
2003-06-11 Alan Modra <amodra@bigpond.net.au>
* gas/macros/app1.d: Ignore section symbols.
diff --git a/gas/testsuite/gas/cfi/cfi-common-3.d b/gas/testsuite/gas/cfi/cfi-common-3.d
new file mode 100644
index 0000000..f82e02e
--- /dev/null
+++ b/gas/testsuite/gas/cfi/cfi-common-3.d
@@ -0,0 +1,21 @@
+#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 00000010 00000018 FDE cie=00000000 pc=.*
+ DW_CFA_advance_loc: 4 to .*
+ DW_CFA_remember_state
+ DW_CFA_restore_state
+
diff --git a/gas/testsuite/gas/cfi/cfi-common-3.s b/gas/testsuite/gas/cfi/cfi-common-3.s
new file mode 100644
index 0000000..d1282d1
--- /dev/null
+++ b/gas/testsuite/gas/cfi/cfi-common-3.s
@@ -0,0 +1,4 @@
+ .cfi_startproc simple
+ .long 0
+ .cfi_escape 10, 11
+ .cfi_endproc
diff --git a/gas/testsuite/gas/cfi/cfi.exp b/gas/testsuite/gas/cfi/cfi.exp
index 968d3b1..6592bbe 100644
--- a/gas/testsuite/gas/cfi/cfi.exp
+++ b/gas/testsuite/gas/cfi/cfi.exp
@@ -34,3 +34,4 @@ if [istarget "x86_64-*"] then {
run_list_test "cfi-diag-1" ""
run_dump_test "cfi-common-1"
run_dump_test "cfi-common-2"
+run_dump_test "cfi-common-3"