This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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" }
 }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]