This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Allow 8-byte absolute FDE addresses on !DIFF_EXPR_OK targets
- From: Richard Sandiford <rdsandiford at googlemail dot com>
- To: binutils at sourceware dot org
- Date: Sat, 16 Aug 2008 19:13:00 +0100
- Subject: Allow 8-byte absolute FDE addresses on !DIFF_EXPR_OK targets
GCC's recent move towards CFI directives exposed a problem for MIPS n64:
FDE addresses were encoded as absolute 32-bit addresses instead of
absolute 64-bit addresses.
(MIPS is unfortunately a !DIFF_EXPR_OK target, although we do of course
make the FDEs use a PC-relative encoding at link time.)
Although we could introduce a new TC macro for this, I thought the easiest
thing would be to reuse DWARF2_ADDR_SIZE. I think any target that defines
that macro would want the same thing for absolute FDEs. The question then
is: what should we do for 16-bit targets? They're currently using 4-byte
addresses too, but I assume 2-byte addresses would be preferable.
Using DWARF2_ADDR_SIZE also means duplicating or moving the dwarf2dbg.c
default. I'd prefer "moving", but I wasn't sure where.
I thought the new fde_addr_size function was a useful abstraction.
It also helps avoid problems with using non-int DWARF2_ADDR_SIZE
values in the switch statement.
Tested on mips64-linux-gnu, i686-pc-linux-gnu and sparc-sun-solaris2.8.
OK to install?
Richard
gas/
* dw2gencfi.c (DWARF2_ADDR_SIZE): Provide default definition.
(fde_addr_size): New function.
(output_cie): Use fde_addr_size to pick an absolute encoding.
(output_fde): Likewise. Use the same size for the code length.
gas/testsuite/
* gas/mips/cfi-n64-1.s, gas/mips/cfi-n64-1.d: New test.
* gas/mips/mips.exp: Run it.
Index: gas/dw2gencfi.c
===================================================================
--- gas/dw2gencfi.c 2008-08-16 18:44:05.000000000 +0100
+++ gas/dw2gencfi.c 2008-08-16 19:07:27.000000000 +0100
@@ -39,6 +39,17 @@
# define tc_cfi_frame_initial_instructions() ((void)0)
#endif
+#ifndef DWARF2_ADDR_SIZE
+# define DWARF2_ADDR_SIZE(bfd) (bfd_arch_bits_per_address (bfd) / 8)
+#endif
+
+#if !defined DIFF_EXPR_OK
+static inline int
+fde_addr_size (void)
+{
+ return DWARF2_ADDR_SIZE (stdoutput);
+}
+#endif
struct cfi_insn_data
{
@@ -1099,7 +1110,23 @@ output_cie (struct cie_entry *cie)
#if defined DIFF_EXPR_OK || defined tc_cfi_emit_pcrel_expr
out_one (DW_EH_PE_pcrel | DW_EH_PE_sdata4);
#else
- out_one (DW_EH_PE_sdata4);
+ switch (fde_addr_size ())
+ {
+ case 2:
+ out_one (DW_EH_PE_sdata2);
+ break;
+
+ case 4:
+ out_one (DW_EH_PE_sdata4);
+ break;
+
+ case 8:
+ out_one (DW_EH_PE_sdata8);
+ break;
+
+ default:
+ abort ();
+ }
#endif
if (cie->first)
@@ -1117,6 +1144,7 @@ output_fde (struct fde_entry *fde, struc
symbolS *after_size_address, *end_address;
expressionS exp;
offsetT augmentation_size;
+ int size;
after_size_address = symbol_temp_make ();
end_address = symbol_temp_make ();
@@ -1135,22 +1163,25 @@ output_fde (struct fde_entry *fde, struc
#ifdef DIFF_EXPR_OK
exp.X_add_symbol = fde->start_address;
exp.X_op_symbol = symbol_temp_new_now ();
- emit_expr (&exp, 4); /* Code offset. */
+ size = 4;
+ emit_expr (&exp, size); /* Code offset. */
#else
exp.X_op = O_symbol;
exp.X_add_symbol = fde->start_address;
exp.X_op_symbol = NULL;
#ifdef tc_cfi_emit_pcrel_expr
- tc_cfi_emit_pcrel_expr (&exp, 4); /* Code offset. */
+ size = 4;
+ tc_cfi_emit_pcrel_expr (&exp, size); /* Code offset. */
#else
- emit_expr (&exp, 4); /* Code offset. */
+ size = fde_addr_size ();
+ emit_expr (&exp, size); /* Code offset. */
#endif
exp.X_op = O_subtract;
#endif
exp.X_add_symbol = fde->end_address;
exp.X_op_symbol = fde->start_address; /* Code length. */
- emit_expr (&exp, 4);
+ emit_expr (&exp, size);
augmentation_size = encoding_size (fde->lsda_encoding);
out_uleb128 (augmentation_size); /* Augmentation size. */
Index: gas/testsuite/gas/mips/cfi-n64-1.s
===================================================================
--- /dev/null 2008-08-16 08:33:17.552097000 +0100
+++ gas/testsuite/gas/mips/cfi-n64-1.s 2008-08-16 18:46:13.000000000 +0100
@@ -0,0 +1,9 @@
+ .global foo
+ .type foo,@function
+ .ent foo
+foo:
+ .cfi_startproc
+ jr $31
+ nop
+ .cfi_endproc
+ .end foo
Index: gas/testsuite/gas/mips/cfi-n64-1.d
===================================================================
--- /dev/null 2008-08-16 08:33:17.552097000 +0100
+++ gas/testsuite/gas/mips/cfi-n64-1.d 2008-08-16 18:46:46.000000000 +0100
@@ -0,0 +1,9 @@
+#as: -64 -EB
+#objdump: -sj.eh_frame
+
+.*
+
+Contents of section \.eh_frame:
+ 0000 00000010 00000000 017a5200 017c1f01 .*
+ 0010 0c0d1d00 00000018 00000018 00000000 .*
+ 0020 00000000 00000000 0000000c 00000000 .*
Index: gas/testsuite/gas/mips/mips.exp
===================================================================
--- gas/testsuite/gas/mips/mips.exp 2008-08-16 18:48:01.000000000 +0100
+++ gas/testsuite/gas/mips/mips.exp 2008-08-16 18:49:38.000000000 +0100
@@ -833,4 +833,5 @@ if { [istarget mips*-*-vxworks*] } {
run_dump_test "mips16-vis-1"
run_dump_test "call-nonpic-1"
+ if $has_newabi { run_dump_test "cfi-n64-1" }
}